5 from AthenaConfiguration.ComponentFactory
import CompFactory
6 from AthenaCommon.Logging
import logging
9 log = logging.getLogger(__name__)
13 '''GenericMonitoringTool configurable class'''
15 __slots__ = (
'_configFlags',
'_convention',
'_defaultDuration')
17 def __init__(self, flags, name='GenericMonitoringTool', **kwargs):
35 @defaultDuration.setter
40 if 'convention' in kwargs:
45 if duration
is not None:
46 kwargs[
'convention'] = self.
convention +
':' + duration
48 if getattr(self,
'HistPath',
'') !=
'':
49 kwargs.setdefault(
'path',
'')
52 self.Histograms.
append(toadd)
62 '''Array of configurables of GenericMonitoringTool objects'''
63 def __init__(self, flags, name, dimensions, **kwargs):
65 self.Postfixes, self.
Accessors = GenericMonitoringArray._postfixes(dimensions)
66 for postfix
in self.Postfixes:
70 '''Forward operator[] on class to the list of tools'''
77 '''Allows one to set attributes of every tool simultaneously
80 member -- string which contains the name of the attribute to be set
81 value -- value of the attribute to be set
84 setattr(tool,member,value)
86 def defineHistogram(self, varname, title=None, path=None, pattern=None, **kwargs):
87 '''Propogate defineHistogram to each tool, adding a unique tag.
90 pattern -- if specified, list of n-tuples of indices for plots to create
92 unAliased = varname.split(
';')[0]
93 _, aliasBase =
_alias(varname)
94 if aliasBase
is None or aliasBase.strip() ==
'':
95 raise ValueError(f
'Unable to define histogram using definition "{varname}" since we cannot determine its name')
96 if pattern
is not None:
100 raise ValueError(
'Argument to GenericMonitoringArray.defineHistogram must be iterable')
101 if not isinstance(pattern, list):
102 pattern =
list(pattern)
103 if len(pattern) == 0:
105 if isinstance(pattern[0], (str, int)):
107 pattern = [(_2,)
for _2
in pattern]
110 accessors = tuple(self.
Accessors[postfix])
111 if pattern
is not None:
112 if accessors
not in pattern:
117 aliasBaseFormatted = aliasBase.format(*accessors)
118 if aliasBaseFormatted==aliasBase:
120 aliased = unAliased+
';'+aliasBase+postfix
123 aliased = unAliased+
';'+aliasBaseFormatted
124 if title
is not None:
125 kwargs[
'title'] = title.format(*accessors)
127 kwargs[
'path'] = path.format(*accessors)
128 except IndexError
as e:
129 log.error(
'In title or path template of histogram {0}, too many positional '\
130 'arguments were requested. Title and path templates were "{1}" and "{2}", '\
131 'while only {3} fillers were given: {4}.'.
format(aliasBase, title,\
132 path, len(accessors), accessors))
135 tool.defineHistogram(aliased, **kwargs)
139 '''Generates a list of subscripts to add to the name of each tool
142 dimensions -- List containing the lengths of each side of the array off tools
143 previous -- Strings appended from the other dimensions of the array
146 assert isinstance(dimensions,list)
and len(dimensions)>0, \
147 'GenericMonitoringArray must have list of dimensions.'
150 return [
''], {
'': [
'']}
151 except AttributeError:
155 accessorDict = collections.OrderedDict()
156 first = dimensions[0]
157 if isinstance(first,list):
159 elif isinstance(first,int):
160 iterable =
range(first)
163 iterable =
list(first)
165 if len(dimensions)==1:
166 postList.append(previous+
'_'+
str(i))
167 accessorDict[previous+
'_'+
str(i)]=[
str(i)]
169 postfixes, accessors = GenericMonitoringArray._postfixes(dimensions[1:],previous+
'_'+
str(i))
170 postList.extend(postfixes)
171 for acckey, accval
in accessors.items():
172 accessorDict[acckey] = [
str(i)] + accval
173 return postList, accessorDict
187 if flags.Common.isOnline:
188 blacklist +=
'=,:.()'
200 variableAliasSplit = varname.split(
';')
201 varList = [v.strip()
for v
in variableAliasSplit[0].
split(
',')]
202 if len(variableAliasSplit)==1:
203 return varList,
'_vs_'.
join(reversed(varList))
204 elif len(variableAliasSplit)==2:
205 return varList, variableAliasSplit[1]
207 message =
'Invalid variable or alias for {}. Histogram(s) not defined.'
208 log.warning(message.format(varname))
219 for key, userVal
in user.items():
221 assert key
in default,\
222 f
'Unknown option {key} provided. Choices are [{", ".join(default)}].'
224 userType =
type(userVal)
225 defaultVal = default[key]
226 defaultType =
type(defaultVal)
227 if isinstance(userVal, bool)
or isinstance(defaultVal, bool):
228 assert isinstance(userVal, bool)
and isinstance(defaultVal, bool),\
229 f
'{key} provided {userType}, expected bool.'
231 assert isinstance(defaultVal, userType),\
232 f
'{key} provided {userType}, expected {defaultType}'
242 'kLBNHistoryDepth': 0,
243 'kAddBinsDynamically':
False,
248 'kCumulative':
False,
250 'kAlwaysCreate':
False
255 elif isinstance(opt, dict):
259 elif isinstance(opt, str)
and len(opt)>0:
261 settings = _options (opt.replace(
',',
' ').
split())
263 elif isinstance(opt,str):
266 elif isinstance(opt, list):
270 kv = o.split(
'=', maxsplit=1)
273 value =
False if kv[1]==
'False' else int(kv[1])
277 assert(
type(settings[key])==
type(value))
278 settings[key] = value
282 assert len(unknown)==0, f
'Unknown option(s) provided: {", ".join(unknown)}.'
284 raise ValueError(
"Unknown opt type")
307 title=None, weight=None,
308 xbins=100, xmin=0, xmax=1, xlabels=None,
309 ybins=None, ymin=None, ymax=None, ylabels=None,
310 zmin=None, zmax=None, zlabels=None,
311 opt=None, convention=None, cutmask=None,
312 treedef=None, merge=None):
315 stringSettingsKeys = [
'xvar',
'yvar',
'zvar',
'type',
'path',
'title',
'weight',
316 'cutMask',
'convention',
'alias',
'treeDef',
'merge']
318 numberSettingsKeys = [
'xbins',
'xmin',
'xmax',
'ybins',
'ymin',
'ymax',
'zbins',
321 arraySettingsKeys = [
'allvars',
'xlabels',
'xarray',
'ylabels',
'yarray',
'zlabels']
323 settings = dict((key,
'')
for key
in stringSettingsKeys)
324 settings.update(dict((key, 0.0)
for key
in numberSettingsKeys))
325 settings.update(dict((key, [])
for key
in arraySettingsKeys))
328 varList, alias =
_alias(varname)
329 if alias
is None or alias.strip() ==
'':
330 log.warning(f
'Unable to define histogram using definition "{varname}" since we cannot determine its name.')
335 log.warning(
'%s is not a valid histogram name. Illegal characters: %s',
336 alias,
' '.
join(invalid))
339 settings[
'alias'] = alias
343 settings[
'xvar'] = varList[0]
345 settings[
'yvar'] = varList[1]
347 settings[
'zvar'] = varList[2]
348 settings[
'allvars'] = varList
352 if flags.Common.isOnline
and type
in [
'TTree']:
353 log.warning(
'Object %s of type %s is not supported for online running and '
354 'will not be added.', varname, type)
358 hist2D = [
'TH2',
'TProfile',
'TEfficiency',
'TTree']
359 hist3D = [
'TProfile2D',
'TEfficiency',
'TTree']
361 assert any([valid2D
in type
for valid2D
in hist2D]),
'Attempting to use two '
362 'monitored variables with a non-2D histogram.'
364 assert any([valid3D
in type
for valid3D
in hist3D]),
'Attempting to use three '
365 'monitored variables with a non-3D histogram.'
366 settings[
'type'] = type
371 settings[
'path'] = path
376 settings[
'title'] = title
379 if weight
is not None:
380 settings[
'weight'] = weight
383 if cutmask
is not None:
384 settings[
'cutMask'] = cutmask
387 if convention
is not None:
388 settings[
'convention'] = convention
392 binTypes = (int, list, tuple)
395 assert isinstance(xbins, binTypes),
'xbins argument must be int, list, or tuple'
396 if isinstance(xbins, int):
397 settings[
'xbins'], settings[
'xarray'] = xbins, []
399 settings[
'xbins'], settings[
'xarray'] = len(xbins)-1, xbins
400 settings[
'xmin'] = xmin
401 settings[
'xmax'] = xmax
404 if ybins
is not None:
405 assert isinstance(ybins, binTypes),
'ybins argument must be int, list, or tuple'
406 if isinstance(ybins, int):
407 settings[
'ybins'], settings[
'yarray'] = ybins, []
409 settings[
'ybins'], settings[
'yarray'] = len(ybins)-1, ybins
411 settings[
'ymin'] = ymin
413 settings[
'ymax'] = ymax
417 settings[
'zmin'] = zmin
419 settings[
'zmax'] = zmax
422 if xlabels
is not None and len(xlabels)>0:
423 assert isinstance(xlabels, (list, tuple)),
'xlabels must be list or tuple'
424 settings[
'xbins'] = len(xlabels)
425 settings[
'xlabels'] = xlabels
426 if ylabels
is not None and len(ylabels)>0:
427 assert isinstance(ylabels, (list, tuple)),
'ylabels must be list or tuple'
428 settings[
'ybins'] = len(ylabels)
429 settings[
'ylabels'] = ylabels
431 if ymin
is None: settings[
"ymin"] = 0
432 if ymax
is None: settings[
"ymax"] = settings[
"ymin"]+1
433 if zlabels
is not None and len(zlabels)>0:
434 assert isinstance(zlabels, (list, tuple)),
'zlabels must be list or tuple'
435 settings[
'zlabels'] = zlabels
438 if treedef
is not None:
439 assert type==
'TTree',
'cannot define tree branches for a non-TTree object'
440 settings[
'treeDef'] = treedef
446 if ((settings[
'kAddBinsDynamically']
or settings[
'kRebinAxes']
or settings[
'kCanRebin'])
447 and (
not flags.Common.isOnline
and 'OFFLINE' in settings[
'convention'])):
449 log.warning(f
'Merge method for {alias} is not specified but needs to be "merge" due to histogram definition; overriding for your convenience')
453 if merge
is not None:
454 assert type
not in [
'TEfficiency',
'TTree',
'TGraph'],
'only default merge defined for non-histogram objects'
455 settings[
'merge'] = merge
458 if settings[
'kLBNHistoryDepth']>0
and flags.Common.isOnline:
459 settings[
'kAlwaysCreate'] =
True
460 log.debug(
'Setting kAlwaysCreate for lumiblock histogram "%s"', varname)
463 assert settings[
'kLBNHistoryDepth']>=0, f
'Histogram "{alias}" has invalid kLBNHistoryDepth.'
464 assert settings[
'kLive']>=0, f
'Histogram "{alias}" has invalid kLive.'
466 assert settings[
'kLBNHistoryDepth']==0
or settings[
'kLive']==0,\
467 f
'Cannot use both kLBNHistoryDepth and kLive for histogram {alias}.'
469 assert settings[
'kLive']==0
or flags.Common.isOnline,\
470 f
'Cannot use kLive with offline histogram {alias}.'
472 return json.dumps(settings)
491 def defineTree(flags, varname, treedef, path=None, title=None,
492 opt='', convention=None,
494 return defineHistogram(flags, varname, type=
'TTree', path=path, title=title,
495 treedef=treedef, opt=opt, convention=convention,