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