7 This module defines various components to be used in AnalysisBase releases.
8 These components (classes, submodules...) can be used in place of some Athena components
9 they are replacing, so athena-style configuration can be used unchanged in AnalysisBase
11 This module is thus designed ONLY for AnalysisBase and to run EventLoop jobs.
13 IMPORTANT : this module is only designed so the jet configuration works. There's no guarantee it won't mess up
14 when used with other part of Athena configuration.
16 Internally, the athena-style configurations of algorithms are translated to AnaReentrantAlgorithmConfig or
17 AnaAlgorithmConfig. The configuration of AsgTools are translated to call to AnaAlgorithmConfig.addPrivateTool()
18 or AnaAlgorithmConfig.setPropertyFromString()
20 This module allows to write python config for EventLoop exactly as one would do for Athena :
22 alg1 = CompFactory.MyAlg("algname",
23 InputContainer = "SomeJets".
25 AprivateTool = CompFactory.SomeTool("tool", AToolparam =0.21), )
26 alg2 = CompFactory.AnOtherAlg( ... )
30 job.addManyAlgs([alg1, alg2]) # specific call allowed by this module
32 driver = ROOT.EL.DirectDriver()
33 driver.submit( job, "out")
38 from types
import ModuleType
45 logging.setLoggerClass( logging.Logger )
49 """Helper function producing a string property value"""
51 stringValue =
str( value )
52 if isinstance( value, bool ):
53 stringValue =
str(
int( value ) )
60 """A simplistic array of Configured (see below) to replace the ToolHandleArray of Athena """
82 tool = anaAlg.addPrivateToolInArray(conf.fullname(), conf.type)
83 conf._name = tool._prefix.split(
'.')[-1]
84 conf.assignAllProperties(anaAlg)
89 """A replacement for Athena auto-generated Configured python class.
90 Configured has the same interface as its Athena counterpart and can describe both Tools and Algorithms
92 This is a base class. The system replacing CompFactory will generate a derived class for each c++ Tool/Algorithm
93 to hold the configuration of such tool/alg (see generateConfigured())
101 _allowed = [
'_properties',
'_name',
'_parent',
'_anaAlg']
107 for k,v
in props.items():
114 raise AttributeError(
"Configuration of Tool {} / {} . can't set attribute : {}".
format(self.type, self.
_name, k) )
122 if isinstance(v, Configured):
124 raise RuntimeError(
"Configuring {} / {} : Tool for property {} already exists".
format(self.type, self.
_name, k) )
128 elif isinstance(v, (list, tuple) ):
129 if isinstance(v[0], Configured):
144 if self.
_parent is None:
return k
148 if self.
_parent is None :
return [self]
153 return '.'.
join([p._name
for p
in parents])
156 return [ (k, getattr(self,k))
for k
in self.
_properties]
159 return self.type+
'/'+self.
_name
163 """Returns this configured alg as an instance of Ana(Reentrant)AlgorithmConfig
165 if issubclass(self._cppclass, ROOT.EL.AnaReentrantAlgorithm):
166 alg=ROOT.EL.AnaReentrantAlgorithmConfig()
168 alg=ROOT.EL.AnaAlgorithmConfig()
176 """If self represents a configured AlgTool,
177 this call will configure the AnaAlgorithmConfig 'anaAlg' so
178 its ToolHandle property 'handlename' is configured with self
180 props = {handlename:self, }
181 klass=
type(
'TmpConf', (Configured,), dict(_allowed=self.
_allowed+[handlename], _propTypes={},
182 type=anaAlg.getType(),_cppclass=
'none') )
184 c=
klass(anaAlg.name(), **props)
185 c.assignAllProperties(anaAlg)
188 """ Transfer all the configuration in self to anaAlg
189 where anaAlg is an AnaAlgorithmConfig."""
196 if isinstance(v , Configured):
198 alg.addPrivateTool(v.fullname(), v.type)
199 v.assignAllProperties(alg)
200 elif isinstance(v, ConfArray ):
202 v.assignAllProperties(alg)
206 alg.setProperty[cpptype](self.
prefixed(k) , v)
216 if issubclass(cppclass, cppyy.gbl.asg.IAsgTool):
217 dummy = cppclass(
'dummy')
219 dummy = cppclass(
'dummy', 0)
222 pm = dummy.getPropertyMgr()
223 propkeys = [
str(k)
for k,p
in pm.getProperties() ]
224 propTypes = dict( (k,
propertyType(pm.getProperty(k)) )
for k
in propkeys)
225 allowedProp = Configured._allowed + [k
for k
in propkeys]
227 klass=
type(classname+
'Conf', (Configured,), dict(_allowed=allowedProp, _propTypes=propTypes,
228 type=prefix+classname,_cppclass=cppclass) )
233 """Guess the type of the TProperty p.
234 p is a C++ instance of a TProperty.
236 This simply interpret the cpp name as set by cppyy...
238 clsname = p.__class__.__cpp_name__
240 typ = clsname[10:-1].strip()
247 """A namespace able to automatically generate Configured when quering attributes :
248 Used to replace CompFactory so that expressions like :
249 tool = CompFactory.Trk.SomeTrkTool("tname", Prop=2.345)
250 tool = CompFactory.getComp("Trk::SomeTrkTool")("tname", Prop=2.345)
252 In the above 2 examples both CompFactory and Trk are ConfNameSpace
255 self.
prefix=name+
"::" if name !=
"" else ""
261 """generates a new Configured class for the C++ class ROOT.classname .
262 This implies there must be a dictionnary for classname.
266 c = self.__dict__.
get(classname,
None)
271 c=getattr(ROOT, self.
prefix+classname,
None)
274 print(
"JetAnalysisCommon ERROR : ",classname,
" is not a known C++ tool, alg, or namespace ")
277 if hasattr(c,
'getPropertyMgr'):
284 setattr(self, classname, conf)
297 CompFactory.addNameSpaces(
'Analysis',
'Trk',
'Jet',
'Sim',)
301 ComponentFactory.CompFactory = CompFactory
303 ComponentFactory.isComponentAccumulatorCfg =
lambda :
True
311 CFElements.parOR = parOR
317 """Provdide similar interface than AthenaConfiguration.ComponentAccumulator and also very simplistic
318 merging of list of algorithms
331 setattr(self, alg._name, alg)
333 def merge(self, ca, sequenceName=""):
334 myTNs =
set( alg.typeAndName()
for alg
in self.
algs)
336 tn = alg.typeAndName()
339 setattr(self, alg._name, alg)
351 """a little configuration function added from the python module JetAnalysisCommon.py to easily schedule
352 # a list of Configured algs as defined by this module."""
354 job.algsAdd( alg.asAnaAlg() )
356 ROOT.EL.Job.addManyAlgs = addManyAlgs
363 JetAnalysisCommon = sys.modules[__name__]
366 sys.modules[
'AthenaConfiguration.ComponentFactory'] = JetAnalysisCommon.ComponentFactory
367 sys.modules[
'AthenaConfiguration.ComponentAccumulator'] = JetAnalysisCommon.ComponentAccumulator
368 sys.modules[
'AthenaCommon.CFElements'] = JetAnalysisCommon.CFElements
372 """Allows to ignore JetRecTools in case this package is not checked out on top of AnalysisBase"""
373 sys.modules[
'JetRecTools'] =
ModuleType(
'JetRecTools')
374 sys.modules[
'JetRecTools.JetRecToolsConfig'] =
ModuleType(
'JetRecToolsConfig')
381 import JetRecConfig.JetRecConfig
as JetRecConfig
390 JetRecConfig.JetRecCfg_original = JetRecConfig.JetRecCfg
392 """Builds the algs with JetRecConfig.JetRecCfg and then make sure
393 they are in proper order.
394 Re-ordering is done manually, according to various input alg type.
396 res = JetRecConfig.JetRecCfg_original(flags, jetdef , returnFinalJetDef)
398 acc , _ = res
if returnFinalJetDef
else (res,
None)
403 if not hasattr(ROOT,
'EventDensityAthAlg'):
405 evtDensityAlgs = [ (i,alg)
for (i,alg)
in enumerate(algs)
if alg._cppclass == ROOT.EventDensityAthAlg ]
406 pjAlgs = [ (i,alg)
for (i,alg)
in enumerate(algs)
if alg._cppclass == ROOT.PseudoJetAlgorithm ]
408 for i,edalg
in evtDensityAlgs:
409 edInput = edalg.EventDensityTool.InputContainer
410 for j,pjalg
in pjAlgs:
412 if edInput == pjalg.OutputContainer:
413 pairsToswap.append( (i,j) )
414 for (i,j)
in pairsToswap:
415 algs[i], algs[j] = algs[j], algs[i]
423 JetRecConfig.JetRecCfg = JetRecCfg_reorder