31 from AthenaCommon
import SystemOfUnits
34 """A python dictionary extended so that each entry in the dict can also be accessed as
37 d = ConfigDict(aKey = 4)
38 d.aKey # --> == 4 is the same as d["aKey"]
39 d.bKey = 12 # now d["bKey"] is existing and set to 12
41 all other usual methods of dictionary are working as expected.
44 dict.__init__(self, **kwargs)
45 for k,v
in kwargs.items():
46 dict.__setattr__(self, k, v)
51 dict.__getattribute__(self,attr)
55 if attr
in [
'keys',
'clear',
'update',
'pop',
'iteritems',
'values',
'setdefault',
'get',
'has_key',
'copy']:
56 print(
'ConfigDict ERROR can not assign attribute ', attr)
58 dict.__setitem__(self, attr, value)
59 dict.__setattr__(self, attr, value)
61 if attr
in [
'keys',
'clear',
'update',
'pop',
'iteritems',
'values',
'setdefault',
'get',
'has_key',
'copy']:
62 print(
'ConfigDict ERROR can not assign attribute ', attr)
64 dict.__setitem__(self, attr, value)
65 dict.__setattr__(self, attr, value)
69 from copy
import deepcopy
71 for k,v
in kwargs.items():
77 """ prints the content of this dict on stdout (default) or in the file 'out' """
79 from sys
import stdout
82 def write(s, e='\n'): _write(s+e)
86 def write(s, e='\n'): writeFunc(
' '+s,e)
87 writeFunc(self.__class__.__name__+
'(')
88 for k,v
in sorted(self.items()):
89 if isinstance(v, ConfigDict):
106 selL = selStr.split(
'&')
110 minL, varL, maxL = zip(*interpL)
111 return minL, varL, maxL
114 """Interpret a selection string in the form '12.3<var<42.0'
116 '12.3<var<42.0' -> returns (12.3, 'var', 42.)
117 'var<42.0' -> returns (None, 'var', 42.)
118 '12.3<var' -> returns (12.3, 'var', None)
122 print(
"JetMonitoring ERROR interpreting selection string ", selStr)
123 print(
"JetMonitoring ERROR can not interpret '>', please use only '<' ")
125 parts = selStr.split(
'<')
126 cmin, cmax = -3.4e38, 3.4e38
131 var, cut = parts[0] ,
float(parts[1])
133 cut, var =
float(parts[0]) ,parts[1]
135 if ismin : cmin = cut
138 cmin, var, cmax = parts
142 return cmin, var, cmax
145 """ interprets 'varName[X]' into ('varName',x) """
147 name, index = name.split(
'[')
149 name, index = name,
''
150 if not index.endswith(
']'):
152 index =
int(index[:-1])
159 """A dictionary specialized for containing the specification of a Athena tool.
164 ConfigDict.__init__(self, **args)
168 from AthenaConfiguration.ComponentFactory
import CompFactory
170 klass = getattr(CompFactory,conf.pop(
'klass'))
172 conf.pop(
'topLevelDir',
None)
173 conf.pop(
'bottomLevelDir',
None)
174 conf.pop(
'defineHistoFunc',
None)
175 for k, v
in conf.items():
176 if isinstance(v,ToolSpec):
177 v.topLevelDir = self.topLevelDir
178 v.bottomLevelDir = self.bottomLevelDir
180 if isinstance(v,list):
182 if isinstance(v[0],ToolSpec):
186 toolSpec.topLevelDir=self.topLevelDir
187 toolSpec.bottomLevelDir=self.bottomLevelDir
188 toolInstances.append( toolSpec.toTool() )
189 conf[k] = toolInstances
193 return ConfigDict.clone(self, name=newname, **args)
197 defineHistoFunc = self.defineHistoFunc
199 defineHistoFunc(self, parentAlg, monhelper , path)
204 """A dictionary specialized to contain a jet variable specification"""
205 def __init__(self, Name , Type='float', Index=-1, Scale=1):
207 if Name.endswith(
':GeV'):
208 Scale=1./SystemOfUnits.GeV
214 if Type[:3] !=
'vec': Type=
'vec'+Type
219 ConfigDict.__init__(self)
223 from AthenaConfiguration.ComponentFactory
import CompFactory
224 self.pop(
'topLevelDir',
None)
225 self.pop(
'bottomLevelDir',
None)
226 return CompFactory.JetHistoVarTool(self.
Name, **self)
238 writeFunc(
str(self))
241 """A dictionary specialized to contain a JetHistoAttributeFiller specification
242 Invocation is like : spec = HistoSpec( name, bins, ...optional args... ) where
243 - name : a string, from which the name of the Histogram is build.
244 AND also the description of variables to be plotted IF none of xvar, yvar or zvar is in the optional args.
245 The final name of histos is given by name.replace(':GeV','').replace(';','_')
246 ex: 'eta' --> histo name : 'eta', variable to plot is 'eta'
247 'pt:GeV' --> histo name : 'pt', variable to plot is 'pt' at GeV scale
248 'pt:GeV;eta' --> histo name : 'pt_eta', 2 variables to plot 'pt' at GeV scale on x axis and 'eta' on y axis
249 - bins : the binning of the histogram in the form (nbin, min, max) or (nbinX, minX, maxX, nbinY, minY, maxY )
250 - optionnal args are :
251 + xvar, yvar, zvar : strings specifying variables
252 + profile : boolean, True if the histo is a TProfile (or TProfile2D)
253 + any other args (ex: title) will be forwarded to the mongroup.defineHistogram() function.
255 def __init__(self, name , bins, xvar=None, yvar=None, zvar=None, profile=False,**args):
265 xv , yv = name.split(
';')
267 self.
yvar = yvar
if yvar
is not None else yv
270 xv , yv, zv = name.split(
';')
271 self.
xvar = xvar
if xvar
is not None else xv
272 self.
yvar = yvar
if yvar
is not None else yv
273 self.
zvar = zvar
if zvar
is not None else zv
275 self.
name = name.replace(
':GeV',
'')
278 ConfigDict.__init__(self, **args)
284 def clone(self, newname, bins=None, xvar=None, yvar=None, zvar=None, **hargs):
285 c = ConfigDict.clone(self)
286 if xvar : c.xvar = xvar
287 if yvar : c.yvar = yvar
288 if zvar : c.zvar = zvar
289 if bins: c.bins = bins
290 c.hargs.update(**hargs)
294 def to2DSpec(self, yspec, profile=False, zspec=None):
295 """ Merge this histo spec and yspec into a new 2D histo spec"""
296 tx, ax, _ = self.title.
split(
';')
297 ty, ay, _ = yspec.title.split(
';')
298 title = ty+
' vs '+tx+
';'+ax+
';'+ay
299 name = self.
name+
';'+yspec.name
300 if zspec
is not None:
301 tz, az, _ = zspec.title.split(
';')
302 title = tz+
' vs '+tx+
' and '+ty+
';'+ax+
';'+ay
304 name = name +
';'+zspec.name
307 yvar = yspec.xvar, title=title, profile=profile
309 if zspec
is not None:
310 s2d.zvar = zspec.xvar
316 from AthenaConfiguration.ComponentFactory
import CompFactory
318 tool = CompFactory.JetHistoAttributeFiller(self.
groupName()+
"hfiller",
326 else: tool.VarZ =
None
327 else : tool.VarY =
None
333 """ This function performs the standard monitoring config calls for this JetHisto tool.
334 - group = monhelper.addGroup( ... )
335 - group.defineHistogram( ... )
342 hargs.update(xbins = bins[0],xmin = bins[1], xmax=bins[2],
346 hargs.update(xbins = bins[0],xmin = bins[1], xmax=bins[2],
347 ybins = bins[3],ymin = bins[4], ymax=bins[5],
348 type=
'TH2F' if not self.
isProfile else 'TProfile',
351 hargs.type =
'TProfile2D'
352 hargs.update( **self.
hargs)
355 bottomLevelDir = self.bottomLevelDir
if self.bottomLevelDir !=
'' else parentAlg.JetContainerName.Path
356 group = monhelper.addGroup(parentAlg, self.
groupName(), self.topLevelDir+bottomLevelDir)
371 group.defineHistogram(name, path=path, **hargs)
375 def write(s): writeFunc(
' '+s)
376 writeFunc(
'HistoSpec("'+self.
name+
'", '+
str(self.
bins) )
377 for k
in [
'xvar',
'yvar',
'zvar',
'isProfile' ]:
378 if self[k]
is not None:
384 """A similar dictionary to HistoSpec above, but specialized to contain a
385 JetHistoEventLevelFiller specification.
386 Invocation is like : spec = EventHistoSpec( name, bins=(n,xlow,xhigh) )
389 ToolSpec.__init__(self, klass=
None, name=name, **args)
394 from JetMonitoring.JetStandardHistoSpecs
import knownEventVar
396 while knownEventVar.get(histname,
None)
is None:
398 histnamesplit = histname.split(
"_")
399 histname = histname.replace(
"_"+histnamesplit[-1],
"")
405 from AthenaConfiguration.ComponentFactory
import CompFactory
406 from JetMonitoring.JetStandardHistoSpecs
import knownEventVar
410 tool = CompFactory.JetHistoEventLevelFiller( self.
name+
"hfiller",
417 hargs = dict(xbins = self.
bins[0],xmin = self.
bins[1], xmax=self.
bins[2],
419 hargs.update( **self.
hargs)
421 bottomLevelDir = self.bottomLevelDir
if self.bottomLevelDir !=
'' else parentAlg.JetContainerName.Path
422 group = monhelper.addGroup(parentAlg, self.
name, self.topLevelDir+bottomLevelDir)
423 group.defineHistogram(self.
histName()+
";"+self.
name, path=path, **hargs)
427 """A dictionary specialized to contain a JetHistoSelectSort specification
428 Invocation is like : spec = SelectSpec( name, , expr, path ) where
429 - name : a string naming the selection being applied
430 - expr : s string, defining a selection in the form '0.123<var<4.567' where var is an attribute/variable
431 - path : optional string, giving the sub-directory into which histos for this selection will be put. if not set, defaults to name.
433 def __init__(self, selname, selexpr, path=None, **args):
434 path = selname
if path
is None else path
438 specname =
'_'.
join(varList)
439 if args.setdefault(
'isEventVariable',
False) :
441 selProp =
'EventSelector'
442 selSpec =
ToolSpec(
'JetEventSelector', specname+
'_sel', Var = VarList, )
446 selSpec =
ToolSpec(
'JetSelectorAttribute', specname+
'_sel', Var = VarList, )
447 selSpec[
'CutMin'] = cminList
448 selSpec[
'CutMax'] = cmaxList
449 args[selProp] = selSpec
451 from JetMonitoring.JetStandardHistoSpecs
import knownSelector
453 selSpec = knownSelector.get(selexpr,
None)
455 print(
"ERROR ", selexpr ,
" is an unknown JetSelector ")
458 args[
'Selector'] = selSpec
462 ConfigDict.__init__(self, **args)
472 from AthenaConfiguration.ComponentFactory
import CompFactory
475 selTool = CompFactory.JetHistoSelectSort(self.
name, SelectedIndex=self.get(
'SelectedIndex',-1), InverseJetSel=self.get(
'InverseJetSel',
False))
476 if hasattr(self,
'Selector'):
477 self.Selector.topLevelDir = self.topLevelDir
478 self.Selector.bottomLevelDir = self.bottomLevelDir
479 selTool.Selector = self.Selector.
toTool()
480 if hasattr(self,
'EventSelector'):
481 self.EventSelector.topLevelDir = self.topLevelDir
482 self.EventSelector.bottomLevelDir = self.bottomLevelDir
483 selTool.EventSelector = self.EventSelector.
toTool()
484 if hasattr(self,
'SortVariable'):
486 suffix =
'_'+self.
name
488 tconf.topLevelDir = self.topLevelDir
489 tconf.bottomLevelDir = self.bottomLevelDir
490 newname = tconf.name
if suffix
in tconf.name
else tconf.name+suffix
491 tconf = tconf.clone(newname=newname)
493 selTool.FillerTools += [ tconf.toTool() ]
498 path = path
if self.
path is None else self.
path
501 tconf.defineHisto(parentAlg, monhelper, path)
505 def write(s,e='\n'): writeFunc(
' '+s,e)
506 def write2(s,e='\n'): writeFunc(
' '+s,e)
507 writeFunc(
'SelectSpec("'+self.
name+
'", path='+self.
path+
',')
508 if hasattr(self,
'Selector' ):
509 write(
' Selector=',
'')
510 self.Selector.
_dump( write2)
511 if hasattr(self,
'EventSelector' ):
512 write(
' EventSelector=',
'')
513 self.EventSelector.
_dump( write2)
514 write(
'FillerTools= [')
521 """A dictionary specialized to contain a JetMonitoringAlg specification"""
523 def __init__(self, name , defaultPath='standardHistos/', TriggerChain='' ,**args):
526 args.setdefault(
'FillerTools',[])
527 args.setdefault(
'topLevelDir',
'Jets/')
528 args.setdefault(
'bottomLevelDir',
'')
529 args.setdefault(
'failureOnMissingContainer',
True)
530 args.setdefault(
'onlyPassingJets',
True)
531 args.setdefault(
'eventFiresAnyJetChain',
False)
532 args.setdefault(
'isExpressStreamJob',
False)
533 ConfigDict.__init__(self, defaultPath=defaultPath, TriggerChain=TriggerChain, **args)
543 from AthenaConfiguration.ComponentFactory
import CompFactory
544 alg = monhelper.addAlgorithm(CompFactory.JetMonitoringAlg, self.
name)
545 alg.TriggerChain = self.TriggerChain
546 alg.JetContainerName = self.JetContainerName
547 alg.FailureOnMissingContainer = self.failureOnMissingContainer
548 alg.OnlyPassingJets = self.onlyPassingJets
549 alg.EventFiresAnyJetChain = self.eventFiresAnyJetChain
550 alg.EnforceExpressTriggers = self.isExpressStreamJob
552 path = self.defaultPath
555 tconf.topLevelDir = self.topLevelDir
556 tconf.bottomLevelDir = self.bottomLevelDir
557 tools.append( tconf.toTool( ))
558 tconf.defineHisto(alg, monhelper, path)
559 alg.FillerTools = tools
563 def write(s,e='\n'): writeFunc(
' '+s,e)
564 def write2(s,e='\n'): writeFunc(
' '+s,e)
565 writeFunc(self.__class__.__name__+
'(')
566 for k,v
in sorted(self.items()):
567 if k ==
'FillerTools':
568 write(
'FillerTools = [')
585 """Return a VarSpec from alias :
586 * if alias is a string look up in JetStandardHistoSpecs.knownVar
587 --> if not found build a VarSpec, assuming alias is an attribute of type float.
588 * if alias is a VarSpec, returns it directly
590 from JetMonitoring.JetStandardHistoSpecs
import knownVar
591 if isinstance(alias, str):
592 conf = knownVar.get(alias,
None)
594 conf=VarSpec( Name=alias, Type=
'float')
601 """Return a ToolSpec from alias : (now with EventInfo or JetContainer variables)
602 * if alias is a string build a ToolSpec, assuming alias is an attribute of type float.
603 * if alias is a ToolSpec, returns it directly
605 from JetMonitoring.JetStandardHistoSpecs
import knownEventVar
606 if isinstance(alias, str):
607 conf = knownEventVar.get(alias,
None)
609 conf =
ToolSpec(
'EventHistoVarTool', alias, Attribute=alias)
616 """Return a HistoSpec from alias :
617 * if alias is a string look up in JetStandardHistoSpecs.knownHistos
618 --> if found, return a full clone (so client can modify it safely)
619 --> if not found and contain a ';' build a HistoSpec for a 2D histograms
620 * if alias is a ToolSpec, returns it directly
622 if isinstance(alias, ToolSpec):
624 elif isinstance(alias,str):
625 from JetMonitoring.JetStandardHistoSpecs
import knownHistos
627 c = knownHistos.get(alias,
None)
631 return c.clone(c.name)
637 aliases = alias.split(
';')
638 aliasX, aliasY = aliases[0], aliases[1]
639 cX = knownHistos.get(aliasX,
None)
640 cY = knownHistos.get(aliasY,
None)
641 if len(aliases) == 2:
643 print(
"ERROR unknown Histo Filler specification ", cX
if cX
is None else cY)
646 return cX.to2DSpec(cY)
649 cZ = knownHistos.get(aliasZ,
None)
655 cZ =
HistoSpec(vZ.Name, (10,0,1) , title=vZ.Name+
';'+vZ.Name+
';', xvar=vZ )
656 return cX.to2DSpec(cY, zspec=cZ)
660 print(
'ERROR can not instantiate a tool from ', alias)