ATLAS Offline Software
hanwriter.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
2 
3 # @package DQHanConfMaker.hanwriter
4 # Module containing the tools to write a DQConfiguration in han format.
5 # @author: andrea.dotti@pi.infn.it
6 # @author: ponyisi@hep.uchicago.edu
7 # 15 August 2008
8 # @note: The content of this module is inspired by the xml.dom.minidom module
9 """
10 This module contains tools to write a DQConfiguration in han format
11 """
12 
13 import DQHanConfMaker
14 from DQConfMakerBase.Helpers import BaseException, toList
15 from DQConfMakerBase.DQElements import DQBase
16 from functools import reduce
17 
18 # Writing exception
19 # Han exception
20 
21 
22 class HanWritingError(BaseException):
23  """
24  This exception is thrown when an error writing the han configuration is encountered
25  """
26 
27  def __init__(self, reason):
28  BaseException.__init__(
29  self, "Cannot create the han file ("+str(reason)+")")
30 
31 # Generic exception
32 # Han exception
33 
34 
35 class HanCannotCreateConf(BaseException):
36  """
37  This exception is thrown when an error creating the han configuration is encountered
38  """
39 
40  def __init__(self, reason):
41  BaseException.__init__(
42  self, "Cannot create configuration ("+str(reason)+")")
43 
44 # Han writer base class
45 # Each valid element that can be written in a han file must inherit from this class
46 
47 
48 class Node(DQHanConfMaker.Node):
49  """
50  This is the base class for each element that can be written in a valid han configuration file.
51  Attributes:
52  - subnodes : a list of Node instances
53  - attributes : a list of attributes associated with the node
54  - acceptChild : a list of Node types that can be accepted as sub nodes
55  - nodeType : the type of the node
56  - name : the name of the node
57  """
58  # Default constructor
59  # @param name: the name of the element @c name: string
60 
61  def __init__(self, name=''):
62  """
63  Create a han node
64  """
65  self.subnodes = None
66  self.attributes = None
67  self.acceptChild = [Node.ALGORITHM, Node.DIR, Node.DOCUMENT, Node.HIST, Node.OUTPUT,
68  Node.REFERENCE, Node.THRESHOLD, Node.LIMIT, Node.COMPALG]
69  self.nodeType = Node.UNKNOWN
70  self.name = name
71 
72  # Creates a valid han block
73  # @param encoding: a valid encoding identifier. @see: module codecs
74  # @return: the han string
75  def tohan(self, encoding=None):
76  """
77  convert the object in a valid han script block
78  """
79  return self.toprettyhan("", "", encoding)
80 
81  # Creates a valid han block
82  # @param indent: used as indentation @c indent: string
83  # @param newl: used as new line character @c newl: string
84  # @param encoding: a valid encoding identifier @see: module codecs
85  # @return: the string representing the han configuration
86  def toprettyhan(self, indent="\t", newl="\n", encoding=None):
87  """
88  convert the object in a formatted han string
89  """
90  # restore the following in a future tdaq release
91  # writer = DQHanConfMaker._get_StringIO()
92  import io
93  import six
94  writer = io.BytesIO() if six.PY2 else io.StringIO()
95  if encoding is not None:
96  import codecs
97  writer = codecs.lookup(encoding)[3](writer)
98  self.writehan(writer, "", indent, newl)
99  return writer.getvalue()
100 
101  # Writes a han block
102  # @param writer: the writer helper @c writer: an object supporting the write method
103  # @param indent: used as indentation @c indent: string
104  # @param addindent: used as additional indentation for each sub node @c addindent: string
105  # @param newl: used as newline at the end of the element @c newl: string
106  def writehan(self, writer, indent="", addindent="", newl=""):
107  """
108  Converts the object in a han string and writes it in the writer object
109  """
110  writer.write(
111  indent+DQHanConfMaker._get_NodeType(self.nodeType)+" "+self.name)
112  # if it is a document do not need to add { }
113  if self.nodeType != Node.DOCUMENT:
114  writer.write(" { %s" % (newl))
115  if self.attributes:
116  for key, attribute in self.attributes.items():
117  writer.write("%s %s = %s%s" % (indent, key, attribute, newl))
118  if self.subnodes:
119  for node in self.subnodes:
120  node.writehan(writer, indent+addindent, addindent, newl)
121  if self.nodeType != Node.DOCUMENT:
122  writer.write("%s}%s" % (indent, newl))
123 
124  # Adds a sub node
125  # @param child: the node to add @c child: a Node object instance
126  # @raise HanCannotCreaqteConf: in case of errors
127  def appendChild(self, child):
128  """
129  Add a sub node to this node
130  """
131  try:
132  if child.nodeType not in self.acceptChild:
133  msg = " Node: "+DQHanConfMaker._get_NodeType(self.nodeType)
134  msg += " Cannot have a child of type:", child.nodeType
135  raise HanCannotCreateConf(msg)
136  except Exception:
137  raise HanCannotCreateConf(
138  "Object:"+str(child)+" is not a valid Node")
139  if not self.subnodes:
140  self.subnodes = []
141  self.subnodes += [child]
142 
143  # Adds an attribute to the node
144  # @param key: the attribute identifier @c key: a string
145  # @param attribute: the value for the attribute @c attribute: a string
146  def setAttribute(self, key, attribute):
147  """
148  The attribute identified by key is added to this node
149  """
150  if not self.attributes:
151  self.attributes = {}
152  self.attributes[key] = attribute
153  # Removes an attribute
154  # @param key: the attribute key @c key: a string
155  # @return: True on success
156 
157  def removeAttribute(self, key):
158  """
159  Removes attribute identified by key
160  """
161  if self.attributes and key in self.attributes:
162  del self.attributes[key]
163  return True
164  return False
165  # Gets the attribute identified by key
166  # @param key: an attribute identifier @c key: string
167  # @return: the corresponding attribute or None if not found
168 
169  def getAttribute(self, key):
170  """
171  Gets the attribute identified by the key, None if not found
172  """
173  if self.attributes and key in self.attributes:
174  return self.attributes[key]
175  return None
176  # Gets a sub-node by name and type
177  # @param name: the sub-node name
178  # @param nodetype: the sub-node type
179  # @return: the found Node or None if not found
180 
181  def getSubNode(self, name, nodetype):
182  """
183  Returns the sub-node identified by name and nodetype
184  """
185  if self.subnodes:
186  for sn in self.subnodes:
187  if sn.nodeType == nodetype and sn.name == name:
188  return sn
189  return None
190 
191  def __str__(self):
192  return "HanNode: "+self.name+" ("+DQHanConfMaker._get_NodeType(self.nodeType)+") Attributes:"+str(self.attributes)+" SubNodes: "+str(self.subnodes)
193 
194 
195 # HanHistogram class
196 # This class represents the configuration for a histogram
198  """
199  A han histogram element is a Node with attributes:
200  - the histogram name
201  - the algorithm to be used
202  - the output where to store the dq result
203  """
204  # Default constructor
205  # @param histogram: the histogram name @c histogram: a string
206  # @param algorithm: the algorithm element name @c algorithm: a string
207  # @param output: the output key @c output: a string
208  # @param annotations: annotations for the DQRegion @c : a dict
209  # @param attributes: attributes for the DQRegion @c : a dict
210  # @note: the histogram name is the histogram name without the directory structure. Thus a HanHistogram is usually nested in a directory tree (@see: HanDir)
211 
212  def __init__(self, histogram, algorithm, annotations={}, output=DQHanConfMaker._default_output, attributes={}):
213  """
214  Creates a han histogram configuration element
215  """
216  Node.__init__(self, histogram)
217  self.acceptChild = []
218  self.nodeType = Node.HIST
219  self.setAttribute('algorithm', algorithm)
220  self.setAttribute('output', output)
221  if 'Weight' in attributes:
222  self.setAttribute('weight', attributes['Weight'][1])
223  for annotation in annotations:
224  self.setAttribute(annotation, annotations[annotation])
225 
226  # Gets the output attribute
227  # @return: the output attribute string
228  def getOutput(self):
229  """
230  Retrieves the output attribute
231  """
232  return self.getAttribute('output')
233 
234  # Gets the algorithm attribute
235  # @return: the algorithm attribute string
236  def getAlgorithm(self):
237  """
238  Retrieves the algorithm attribute
239  """
240  return self.getAttribute('algorithm')
241 
242 # Class algorithm
243 # This class implements the han representation of a DQAlgorithm element
244 
245 
247  """
248  The han representation of a DQAlgorithm
249  """
250  # Default constructor
251  # @param name: the identifier for the han algorithm @c name: a string
252  # @param algoname: the dqm_algorithm name @c algoname: a string
253  # @param libname: the library containing the algorithm @c libname: a string
254  # @param reference: the reference object, can be None
255  # @param thresholds: the thresholds objects, can be None
256  # @param parameters: additional parameters, can be empty. @c parameters: a list
257 
258  def __init__(self, name, algoname, libname='libdqm_algorithms.so', reference=None, thresholds=None,
259  parameters={}):
260  """
261  Creates a han algorithm configuration element
262  """
263  Node.__init__(self, name)
264  self.acceptChild = [Node.THRESHOLD, Node.REFERENCE]
265  self.nodeType = Node.ALGORITHM
266  self.setAttribute('name', algoname)
267  if libname:
268  self.setAttribute('libname', libname)
269  if reference:
270  self.setAttribute('reference', reference)
271  if thresholds:
272  self.setAttribute('thresholds', thresholds)
273  for parameter in parameters:
274  self.setAttribute(parameter, parameters[parameter])
275 
276 # Class for composite algorithm
277 # This class implements the han representation of a DQCompositeAlgorithm
278 
279 
281  """
282  The han representation of a CompositeAlgorithm
283  """
284  # Default constructor
285  # @param name: the identifier for the han algorithm @c name: a string
286  # @param algoname: the dqm_algorithm name @c algoname: a string
287  # @param libname: the library containing the algorithm @c libname: a string
288 
289  def __init__(self, name, subalgnames=[], libnames=[]):
290  """
291  Creates a han composite algorithm configuration element
292  """
293  Node.__init__(self, name)
294  self.acceptChild = []
295  self.nodeType = Node.COMPALG
296  self.setAttribute('subalgs', ','.join(subalgnames))
297  self.setAttribute('libnames', ','.join(libnames))
298 
299 # Class for reference
300 # This class implements the han representation of a DQReference
301 
302 
304  """
305  The han representation of a DQReference
306  """
307  # Default constructor
308  # @param name: the identifier for the han reference @c name: a string
309  # @param histogramname: the histogram name @c histogramname: a string
310  # @param file: the filename for the reference histogram @c file: a string
311 
312  def __init__(self, name, histogramname, file, info=None):
313  """
314  Creates a han reference configuration element
315  """
316  Node.__init__(self, name)
317  self.setAttribute('name', histogramname)
318  self.setAttribute('file', file)
319  if info is not None:
320  self.setAttribute('info', info)
321  self.nodeType = Node.REFERENCE
322  self.acceptChild = []
323 
324 # Class for limit
325 # This class implements the han representation of a DQLimit
326 
327 
328 class HanLimit(Node):
329  """
330  The han representation of a limit for a HanThreshold
331  """
332  # Default constructor
333  # @param name: the name of the limit @c name: a string
334  # @param warning: the value for the warning level
335  # @param error: the value for the error level
336 
337  def __init__(self, name, warning, error):
338  """
339  Creates a han limit object
340  """
341  Node.__init__(self, name)
342  self.nodeType = Node.LIMIT
343  self.acceptChild = []
344  self.setAttribute('warning', warning)
345  self.setAttribute('error', error)
346 
347 # Class for threshold
348 # This class implements the han representation of a DQThreshold
349 
350 
352  """
353  The han representation of a DQThreshold
354  """
355  # Default constructor
356  # @param name: the threshold identifier @c name: a string
357 
358  def __init__(self, name):
359  """
360  Creates a han threshold configuration element
361  """
362  Node.__init__(self, name)
363  self.acceptChild = [Node.LIMIT]
364  self.nodeType = Node.THRESHOLD
365 
366  def addLimit(self, name, warning, error):
367  """
368  Adds a limit to the threshold
369  @param name: the limits name
370  @param warning: the limit value for the warning level
371  @param error: the limit value for the error level
372  """
373  if self.getSubNode(name, Node.LIMIT):
374  raise HanCannotCreateConf(
375  "The limit: "+name+" already exists for threshold: "+self.name)
376  limit = HanLimit(name, warning, error)
377  self.appendChild(limit)
378 
379 # Class for han directory
380 # This class implements the han directory
381 
382 
383 class HanDir(Node):
384  """
385  Class representing a dir element
386  A han dir element is a Node with sub nodes of type HanDir or HanHisto
387  """
388  # Default constructor
389  # @param namne: the name of the directory @c name: a string
390 
391  def __init__(self, name):
392  """
393  Creates a han directory element
394  """
395  Node.__init__(self, name)
396  self.acceptChild = [Node.DIR, Node.HIST]
397  self.nodeType = Node.DIR
398 
399  # Adds a sub directory
400  # @param name: the name of the subdirectory @c name: a string
401  # @return: the created HanDir object
402  def addSubDir(self, name):
403  """
404  Adds a subdirectory called name to the current directory and returns the newly created sub directory
405  """
406  subdir = HanDir(name)
407  self.appendChild(subdir)
408  return subdir
409  # Adds a histogram to the current directory
410  # @param histogram: the name of the histogram @c histogram: a string
411  # @param algorithm: the algorithm name to be used for this check @c algorithm: a string
412  # @param annotations: annotations for the DQRegion @c : a dict
413  # @param attributes: attributes for the DQRegion @c : a dict
414  # @param output: the output path for the result @c output: a string
415  # @return: the created HanHistogram object
416 
417  def addHistogram(self, histogram, algorithm, annotations={}, output=DQHanConfMaker._default_output, attributes={}):
418  """
419  Adds to the directory a histogram specifying the histogram name, the algorithm and the output path.
420  """
421  histo = HanHistogram(histogram, algorithm,
422  annotations, output, attributes)
423  self.appendChild(histo)
424  return histo
425  # Gets a sub-directory name
426  # @param name: the subdirectory name @c name: a string
427 
428  def getSubDir(self, name):
429  """
430  returns the sub-directory called name
431  """
432  return self.getSubNode(name, Node.DIR)
433 
434 # Class for han output
435 # This class implements the han output
436 
437 
439  """
440  Class representing a output element
441  A han output element is a Node with sub nodes of type output and with the optional attribute algorithm
442  attribute:
443  - father: the HanOutput that contains this HanOutput
444  """
445  # Default constructor
446  # @param name: the output name @c name: a string
447  # @param algorithm: the optional algorithm name for this summary @c algorithm: summary
448  # @param father: the HanOutput containing this node
449  # @param annotations: annotations for the DQRegion @c : a dict
450  # @param attributes: attributes for the DQRegion @c : a dict
451 
452  def __init__(self, name, algorithm=None, father=None, annotations={}, attributes={}):
453  """
454  Creates an output han element
455  """
456  Node.__init__(self, name)
457  self.acceptChild = [Node.OUTPUT]
458  self.nodeType = Node.OUTPUT
459  if algorithm:
460  self.setAttribute('algorithm', algorithm)
461  self.father = father
462  if 'Weight' in attributes:
463  self.setAttribute('weight', attributes['Weight'][1])
464  for annotation in annotations:
465  self.setAttribute(annotation, annotations[annotation])
466 
467  # Gets the algorithm
468  # @return: the associated algorithm name
469  def getAlgorithm(self):
470  """
471  Gets the algorithm attribute
472  """
473  if 'algorithm' in self.attributes:
474  return self.getAttribute('algorithm')
475  # Adds a sub-output
476  # @param name: the sub output name @c name: a string
477  # @param algorithm: the algorithm for the sub output @c : a string
478  # @param annotations: annotations for the DQRegion @c : a dict
479  # @param attributes: attributes for the DQRegion @c : a dict
480  # @return: the created HanOutput object
481 
482  def addOutput(self, name, algorithm, annotations, attributes):
483  """
484  Adds a sub output element with name and algorithm
485  """
486  subnode = HanOutput(name, algorithm, self, annotations, attributes)
487  self.appendChild(subnode)
488  return subnode
489  # Creates the complete output string
490  # @param append: string to be appended to the name @c append: a string
491  # @param delimter: the delimiting characters for the string concatenation @c delimiter: a string
492  # @return: the complete path output string
493 
494  def getOutputPath(self, append=None, delimiter="/"):
495  """
496  Creates the complete path of this output directory
497  """
498  name = self.name
499  if append:
500  name = name + append
501  if self.father:
502  name = self.father.getOutputPath(delimiter+name, delimiter)
503  return name
504 
505 # Class document
506 # This class represents the han document.
507 # This class is a set of nodes
508 
509 
511  """
512  Class representing a han document
513  """
514  # Default constructor
515  # @param top_level_algorithm: the algorithm name for the top level output
516 
517  def __init__(self, top_level_algorithm='WorstCaseSummary'):
518  """
519  Creates an empty han document with a top level output
520  """
521  HanDir.__init__(self, '')
522  HanOutput.__init__(self, '')
523  self.nodeType = Node.DOCUMENT
524  self.acceptChild = [Node.ALGORITHM, Node.DIR, Node.HIST, Node.OUTPUT, Node.REFERENCE, Node.THRESHOLD,
525  Node.COMPALG]
526  self.root_output_level = HanOutput('top_level', top_level_algorithm)
527  self.appendChild(self.root_output_level)
528  # Adds an output subdirectory
529  # @param name: the sub output name @c name: a string
530  # @param algorithm: the algorithm for the sub output @c algorithm : a string
531  # @param annotations: annotations for the DQRegion @c annotations : a dict
532  # @param attributes: attributes for the DQRegion @c attributes : a dict
533  # @return: the created HanOutput object
534 
535  def addOutput(self, name, algorithm, annotations={}, attributes={}):
536  """
537  Adds a sub output element with name and algorithm
538  """
539  # forward to root region
540  return HanOutput.addOutput(self.root_output_level, name, algorithm, annotations, attributes)
541  # Gets the algorithm object
542  # @param name: the name of the algorithm
543  # @return: the algorithm associated to name
544 
545  def getAlgorithm(self, name):
546  """
547  retrieves the algorithm han object associated with name
548  """
549  return self.getSubNode(name, Node.ALGORITHM)
550  # Gets the reference object
551  # @param name: the reference name
552  # @return: the HanReference object
553 
554  def getReference(self, name):
555  """
556  retrieves the han reference associated with name
557  """
558  return self.getSubNode(name, Node.REFERENCE)
559 
560 
561 # Add a DQParameter object to the HanDocument
562 # @param handocument: the document containing the configuration @c handocument: a HanDocument object
563 # @param dqparameter: the DQParameter object @c dqparameter: a DQParameter object
564 # @param output: the output element for the result
565 # @note: This function is used internally and should not be used by users of this module
566 def _hanAddDQParameter(handocument, dqparameter, output=DQHanConfMaker._default_output):
567  """
568  Add a DQParameter object to a HanDocument, Doing this it creates the tree of
569  dir and output.
570  """
571  try:
572  if dqparameter.type != "DQParameter": # This is not valid
573  raise HanCannotCreateConf(
574  "Object: "+str(dqparameter)+" type does not match 'DQParameter'")
575  # gets the directory structure of the histogram and add it, if needed to the document
576  histoname = dqparameter.getInput().split('/')
577  theDir = handocument
578  # add directories to han document if needed
579  for directory in histoname[0:len(histoname)-1]:
580  subdir = theDir.getSubDir(directory)
581  if subdir is None:
582  subdir = theDir.addSubDir(directory)
583  theDir = subdir
584  # prepare to build the han algorithm element
585  algo = dqparameter.getAlgorithm()
586  if algo is None:
587  raise Exception('DQParameter without DQAlgorithm')
588  dqalgoname, dqalgolibrary = algo.id, algo.getLibraryName()
589  # Build the han reference, if any, associated to this DQParameter
590  dqrefname, dqreference, refs = "", dqparameter.getReference(), []
591  if dqreference != [None]: # References are defined
592  refs = '[%s]' % (','.join(_.id for _ in dqreference))
593  for iref in dqreference:
594  ref = iref.id
595  # search if reference is already in the han document
596  if handocument.getReference(ref) is None:
597  # it's not found, let's create it
598  refcompletename = iref.getReference()
599  filename = refcompletename.rpartition(':')[0]
600  refhistoname = refcompletename.rpartition(':')[
601  2].lstrip('/')
602  hanref = HanReference(
603  ref, histogramname=refhistoname, file=filename,
604  info=iref.getAnnotation('info'))
605  handocument.appendChild(hanref)
606  dqrefname = '_'+ref
607  # build the han thresholds
608  # here it's quite tricky: we have to get two sets of DQThresholds and combine them in a single
609  # han thresholds element
610  warnings = toList(dqparameter.getWarnings())
611  errors = toList(dqparameter.getErrors())
612  thresholds, hanthreshold, thresholdsname = '', None, ''
613  if (warnings != [None]) and (errors != [None]):
614  # Found errors and warnings limits
615  thresholds = dqparameter.id.replace(
616  '_', '__').replace('/', '_')+'_thr'
617  hanthreshold = HanThreshold(thresholds)
618  thresholdsname = thresholds
619  thresholds = '_'+thresholds
620 
621  def getCorrespondingRed(warningname):
622  for e in errors:
623  if e.getAttribute('Name')[1] == warningname:
624  return e
625  return None
626  for warning in warnings:
627  warningname = warning.getAttribute('Name')[1]
628  error = getCorrespondingRed(warningname)
629  if error is None:
630  raise HanCannotCreateConf(
631  'Cannot find corresponding error for warning names: '+warning.id)
632  hanthreshold.addLimit(warningname, warning.getAttribute(
633  'Value')[1], error.getAttribute('Value')[1])
634  #print DQHanConfMaker._get_NodeType(hanthreshold.nodeType),hanthreshold.name
635  handocument.appendChild(hanthreshold)
636 
637  # build the parameter id string and key, value pairs
638  parameterstr = '_'.join([x.id for x in toList(
639  dqparameter.getAlgorithmParameters()) if x is not None])
640  parameters = {}
641  for x in toList(dqparameter.getAlgorithmParameters()):
642  if x is None:
643  continue
644  parameters[x.getName()[1]] = x.getValue()[1][0]
645  # create a unique string identifying this han algorithm element so far
646  hanalgoname = ("%s_%s%s%s%s" % (dqalgolibrary, dqalgoname,
647  dqrefname, thresholds.replace('/', '_'), parameterstr))
648  # Finally add the histogram han element
649  theDir.addHistogram(histogram=histoname[len(histoname)-1], algorithm=hanalgoname,
650  annotations=dqparameter.getAllAnnotations(), output=output, attributes=dqparameter.getAllAttributes())
651  # search the han algorithm in the document
652  if handocument.getAlgorithm(hanalgoname) is None:
653  # This algorithm has never been added before in the document
654  node = HanAlgorithm(name=hanalgoname, algoname=dqalgoname, libname=dqalgolibrary,
655  reference=refs, thresholds=thresholdsname, parameters=parameters)
656  handocument.appendChild(node)
657  # check for possible composite algorithms
658  compalg = algo.getCompositeAlgorithm()
659  if compalg is not None:
660  node = HanCompositeAlgorithm(name=compalg.id, subalgnames=compalg.getSubAlgNames(),
661  libnames=compalg.getLibNames())
662  handocument.appendChild(node)
663  except Exception as msg:
664  raise HanCannotCreateConf(
665  "Object: "+str(dqparameter)+" is not a valid DQParameter. Reason: "+str(msg))
666 
667 # Finds the root han objects of the input collection
668 # @param input: the list of objects @c input: a list of DQBase objects
669 # @raise HanCannotCreateConf: in case of errors
670 # @return: the list of roots
671 # @note: This function is used internally and should not be used by users of this module
672 
673 
674 def _findRoots(input=[], objecttype="DQRegion"):
675  """
676  This helper return the list of objects that are the roots in the tree represented by input.
677  """
678  result = []
679  for o in input:
680  try:
681  if o.type == objecttype:
682  if len(o.isReferencedBy) == 0:
683  result += [o]
684  except Exception:
685  raise HanCannotCreateConf(
686  "object %s is not a valid DQBase object" % o)
687  return result
688 
689 # Gets all DQBase objects that corresponds to the input han objects
690 # @param rootlist: a list of han object trees
691 # @return: the list of all DQBaseObjects associated to each node of the input tree
692 # @note: This function is used internally and should not be used by users of this module
693 
694 
695 def _findAllDQBaseObjects(rootlist):
696  """
697  This returns all DQBase objects reachable from the rootlist as a set.
698  """
699  import operator
700 
701  def recurse(dqbase):
702  if dqbase is None:
703  return set()
704  if isinstance(dqbase, list):
705  return reduce(operator.ior, [recurse(x) for x in dqbase])
706  if not isinstance(dqbase, DQBase):
707  raise ValueError(
708  '%s is not a valid DQBase object; this should never happen' % dqbase)
709  retset = {dqbase}
710  for rel in dqbase.getAllRelatedObjects():
711  retset |= recurse(rel)
712  return retset
713 
714  topset = set()
715  for dqbase in toList(rootlist):
716  topset |= recurse(dqbase)
717  return list(topset)
718 
719 # Writes the han configuration to a file
720 # @param roots: the list of all roots of han trees
721 
722 
723 def writeHanConfiguration(filename='dq.han.config', roots=[]):
724  """
725  Writes the configuration to a han file.
726  The configuration has to be passed as a list of roots in han configuration.
727  """
728  configList = _findAllDQBaseObjects(roots)
729  # First remove the configuration elements that cannot be saved as han
730  for element in configList:
731  try:
732  if not DQHanConfMaker._isAceptedHanElement(element):
733  print("==========WARNING===========")
734  print("Object: " + \
735  str(element) + \
736  " does not have a valid han representation, cannot save")
737  print("The object is referenced by:", element.isReferencedBy)
738  print("You may need to manually edit the configuration")
739  print("============================")
740  configList.remove(element)
741  except Exception:
742  print(element.isReferencedBy)
743  raise HanCannotCreateConf("Not valid object:" + str(element))
744  # Let's create the han document
745  doc = Document()
746  # Find all root regions
747  rootregions = _findRoots(configList)
748 
749  # Navigate through DQRegions tree and add it to the han document
750  def _addchild(hanfather, dqregion, handocument):
751  outputalgo = dqregion.getAlgorithm()
752  if handocument.getAlgorithm(outputalgo.id) is None:
753  # Add to the document the summary maker algorithm
754  # summary makers do not have thresholds or parameters
755  # @todo: in the future extend this to make in enough general to support parameter
756  handocument.appendChild(HanAlgorithm(
757  outputalgo.id, outputalgo.id, outputalgo.getLibraryName())) # , reference, thresholds)
758  output = hanfather.addOutput(dqregion.id, outputalgo.id, annotations=dqregion.getAllAnnotations(
759  ), attributes=dqregion.getAllAttributes())
760  # recursively add subregions
761  for subregion in dqregion.getSubRegions():
762  if subregion is not None:
763  _addchild(output, subregion, doc)
764  # Add each DQParameter to the han document with the helper
765  for parameter in dqregion.getDQParameters():
766  if parameter is not None:
767  _hanAddDQParameter(handocument, parameter,
768  output=output.getOutputPath())
769 
770  for region in rootregions:
771  _addchild(doc, region, doc)
772 
773  fileout = open(filename, 'w')
774  print(doc.toprettyhan(" "), file=fileout)
775 
python.hanwriter.HanOutput
Definition: hanwriter.py:438
python.hanwriter.HanOutput.getAlgorithm
def getAlgorithm(self)
Definition: hanwriter.py:469
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
python.hanwriter.Node.toprettyhan
def toprettyhan(self, indent="\t", newl="\n", encoding=None)
Definition: hanwriter.py:86
python.hanwriter.HanDir.addHistogram
def addHistogram(self, histogram, algorithm, annotations={}, output=DQHanConfMaker._default_output, attributes={})
Definition: hanwriter.py:417
python.hanwriter.HanOutput.getOutputPath
def getOutputPath(self, append=None, delimiter="/")
Definition: hanwriter.py:494
python.hanwriter.HanHistogram.getAlgorithm
def getAlgorithm(self)
Definition: hanwriter.py:236
python.hanwriter.HanDir.getSubDir
def getSubDir(self, name)
Definition: hanwriter.py:428
python.hanwriter.Node.setAttribute
def setAttribute(self, key, attribute)
Definition: hanwriter.py:146
python.hanwriter.Node.getAttribute
def getAttribute(self, key)
Definition: hanwriter.py:169
python.hanwriter.HanThreshold.addLimit
def addLimit(self, name, warning, error)
Definition: hanwriter.py:366
python.hanwriter.HanReference.__init__
def __init__(self, name, histogramname, file, info=None)
Definition: hanwriter.py:312
python.hanwriter.Node.getSubNode
def getSubNode(self, name, nodetype)
Definition: hanwriter.py:181
python.hanwriter.HanHistogram.__init__
def __init__(self, histogram, algorithm, annotations={}, output=DQHanConfMaker._default_output, attributes={})
Definition: hanwriter.py:212
python.hanwriter.HanOutput.addOutput
def addOutput(self, name, algorithm, annotations, attributes)
Definition: hanwriter.py:482
python.hanwriter.HanWritingError.__init__
def __init__(self, reason)
Definition: hanwriter.py:27
python.hanwriter.HanCannotCreateConf.__init__
def __init__(self, reason)
Definition: hanwriter.py:40
python.hanwriter.Document.__init__
def __init__(self, top_level_algorithm='WorstCaseSummary')
Definition: hanwriter.py:517
python.hanwriter.Node.removeAttribute
def removeAttribute(self, key)
Definition: hanwriter.py:157
python.hanwriter.Node.tohan
def tohan(self, encoding=None)
Definition: hanwriter.py:75
python.hanwriter.Node.appendChild
def appendChild(self, child)
Definition: hanwriter.py:127
python.hanwriter._findRoots
def _findRoots(input=[], objecttype="DQRegion")
Definition: hanwriter.py:674
dq_make_web_display.recurse
def recurse(rdir, dqregion, ignorepath, reffile=None)
Definition: dq_make_web_display.py:22
reduce
void reduce(HepMC::GenEvent *ge, std::vector< HepMC::GenParticlePtr > toremove)
Remove unwanted particles from the event, collapsing the graph structure consistently.
Definition: FixHepMC.cxx:84
python.hanwriter.HanLimit
Definition: hanwriter.py:328
python.hanwriter._hanAddDQParameter
def _hanAddDQParameter(handocument, dqparameter, output=DQHanConfMaker._default_output)
Definition: hanwriter.py:566
python.hanwriter.Node.name
name
Definition: hanwriter.py:70
python.hanwriter.HanHistogram
Definition: hanwriter.py:197
python.hanwriter.HanThreshold
Definition: hanwriter.py:351
python.hanwriter.HanAlgorithm.__init__
def __init__(self, name, algoname, libname='libdqm_algorithms.so', reference=None, thresholds=None, parameters={})
Definition: hanwriter.py:258
python.hanwriter.HanCannotCreateConf
Definition: hanwriter.py:35
python.hanwriter.HanLimit.__init__
def __init__(self, name, warning, error)
Definition: hanwriter.py:337
python.hanwriter.Node.nodeType
nodeType
Definition: hanwriter.py:69
python.hanwriter.Document
Definition: hanwriter.py:510
python.hanwriter.HanAlgorithm
Definition: hanwriter.py:246
python.hanwriter.HanHistogram.getOutput
def getOutput(self)
Definition: hanwriter.py:228
python.hanwriter.Document.root_output_level
root_output_level
Definition: hanwriter.py:526
python.hanwriter.Node.__str__
def __str__(self)
Definition: hanwriter.py:191
python.hanwriter._findAllDQBaseObjects
def _findAllDQBaseObjects(rootlist)
Definition: hanwriter.py:695
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.hanwriter.Document.addOutput
def addOutput(self, name, algorithm, annotations={}, attributes={})
Definition: hanwriter.py:535
python.hanwriter.HanDir
Definition: hanwriter.py:383
python.hanwriter.HanOutput.father
father
Definition: hanwriter.py:461
python.hanwriter.HanWritingError
Definition: hanwriter.py:22
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.hanwriter.HanOutput.__init__
def __init__(self, name, algorithm=None, father=None, annotations={}, attributes={})
Definition: hanwriter.py:452
python.hanwriter.Node
Definition: hanwriter.py:48
python.hanwriter.HanDir.__init__
def __init__(self, name)
Definition: hanwriter.py:391
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.hanwriter.HanCompositeAlgorithm
Definition: hanwriter.py:280
python.hanwriter.Node.writehan
def writehan(self, writer, indent="", addindent="", newl="")
Definition: hanwriter.py:106
Trk::open
@ open
Definition: BinningType.h:40
python.hanwriter.Node.acceptChild
acceptChild
Definition: hanwriter.py:67
python.hanwriter.Document.getAlgorithm
def getAlgorithm(self, name)
Definition: hanwriter.py:545
python.hanwriter.Node.subnodes
subnodes
Definition: hanwriter.py:65
python.hanwriter.Node.attributes
attributes
Definition: hanwriter.py:66
python.hanwriter.HanReference
Definition: hanwriter.py:303
python.hanwriter.HanCompositeAlgorithm.__init__
def __init__(self, name, subalgnames=[], libnames=[])
Definition: hanwriter.py:289
python.hanwriter.HanDir.addSubDir
def addSubDir(self, name)
Definition: hanwriter.py:402
str
Definition: BTagTrackIpAccessor.cxx:11
python.hanwriter.Document.getReference
def getReference(self, name)
Definition: hanwriter.py:554
python.hanwriter.HanThreshold.__init__
def __init__(self, name)
Definition: hanwriter.py:358
python.hanwriter.Node.__init__
def __init__(self, name='')
Definition: hanwriter.py:61
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.hanwriter.writeHanConfiguration
def writeHanConfiguration(filename='dq.han.config', roots=[])
Definition: hanwriter.py:723