10 This module contains tools to write a DQConfiguration in han format
14 from DQConfMakerBase.Helpers
import BaseException, toList
15 from DQConfMakerBase.DQElements
import DQBase
16 from functools
import reduce
24 This exception is thrown when an error writing the han configuration is encountered
28 BaseException.__init__(
29 self,
"Cannot create the han file ("+
str(reason)+
")")
37 This exception is thrown when an error creating the han configuration is encountered
41 BaseException.__init__(
42 self,
"Cannot create configuration ("+
str(reason)+
")")
48 class Node(DQHanConfMaker.Node):
50 This is the base class for each element that can be written in a valid han configuration file.
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
67 self.
acceptChild = [Node.ALGORITHM, Node.DIR, Node.DOCUMENT, Node.HIST, Node.OUTPUT,
68 Node.REFERENCE, Node.THRESHOLD, Node.LIMIT, Node.COMPALG]
77 convert the object in a valid han script block
88 convert the object in a formatted han string
93 writer = io.StringIO()
94 if encoding
is not None:
96 writer = codecs.lookup(encoding)[3](writer)
97 self.
writehan(writer,
"", indent, newl)
98 return writer.getvalue()
105 def writehan(self, writer, indent="", addindent="", newl=""):
107 Converts the object in a han string and writes it in the writer object
110 indent+DQHanConfMaker._get_NodeType(self.
nodeType)+
" "+self.
name)
113 writer.write(
" { %s" % (newl))
116 writer.write(
"%s %s = %s%s" % (indent, key, attribute, newl))
119 node.writehan(writer, indent+addindent, addindent, newl)
121 writer.write(
"%s}%s" % (indent, newl))
128 Add a sub node to this node
132 msg =
" Node: "+DQHanConfMaker._get_NodeType(self.
nodeType)
133 msg +=
" Cannot have a child of type:", child.nodeType
137 "Object:"+
str(child)+
" is not a valid Node")
147 The attribute identified by key is added to this node
158 Removes attribute identified by key
170 Gets the attribute identified by the key, None if not found
182 Returns the sub-node identified by name and nodetype
186 if sn.nodeType == nodetype
and sn.name == name:
198 A han histogram element is a Node with attributes:
200 - the algorithm to be used
201 - the output where to store the dq result
211 def __init__(self, histogram, algorithm, annotations={}, output=DQHanConfMaker._default_output, attributes={}):
213 Creates a han histogram configuration element
215 Node.__init__(self, histogram)
220 if 'Weight' in attributes:
222 for annotation
in annotations:
229 Retrieves the output attribute
237 Retrieves the algorithm attribute
247 The han representation of a DQAlgorithm
257 def __init__(self, name, algoname, libname='libdqm_algorithms.so', reference=None, thresholds=None,
260 Creates a han algorithm configuration element
262 Node.__init__(self, name)
272 for parameter
in parameters:
281 The han representation of a CompositeAlgorithm
288 def __init__(self, name, subalgnames=[], libnames=[]):
290 Creates a han composite algorithm configuration element
292 Node.__init__(self, name)
304 The han representation of a DQReference
311 def __init__(self, name, histogramname, file, info=None):
313 Creates a han reference configuration element
315 Node.__init__(self, name)
329 The han representation of a limit for a HanThreshold
338 Creates a han limit object
340 Node.__init__(self, name)
352 The han representation of a DQThreshold
359 Creates a han threshold configuration element
361 Node.__init__(self, name)
367 Adds a limit to the threshold
368 @param name: the limits name
369 @param warning: the limit value for the warning level
370 @param error: the limit value for the error level
374 "The limit: "+name+
" already exists for threshold: "+self.
name)
375 limit =
HanLimit(name, warning, error)
384 Class representing a dir element
385 A han dir element is a Node with sub nodes of type HanDir or HanHisto
392 Creates a han directory element
394 Node.__init__(self, name)
403 Adds a subdirectory called name to the current directory and returns the newly created sub directory
416 def addHistogram(self, histogram, algorithm, annotations={}, output=DQHanConfMaker._default_output, attributes={}):
418 Adds to the directory a histogram specifying the histogram name, the algorithm and the output path.
421 annotations, output, attributes)
429 returns the sub-directory called name
439 Class representing a output element
440 A han output element is a Node with sub nodes of type output and with the optional attribute algorithm
442 - father: the HanOutput that contains this HanOutput
451 def __init__(self, name, algorithm=None, father=None, annotations={}, attributes={}):
453 Creates an output han element
455 Node.__init__(self, name)
461 if 'Weight' in attributes:
463 for annotation
in annotations:
470 Gets the algorithm attribute
481 def addOutput(self, name, algorithm, annotations, attributes):
483 Adds a sub output element with name and algorithm
485 subnode =
HanOutput(name, algorithm, self, annotations, attributes)
495 Creates the complete path of this output directory
511 Class representing a han document
516 def __init__(self, top_level_algorithm='WorstCaseSummary'):
518 Creates an empty han document with a top level output
520 HanDir.__init__(self,
'')
521 HanOutput.__init__(self,
'')
523 self.
acceptChild = [Node.ALGORITHM, Node.DIR, Node.HIST, Node.OUTPUT, Node.REFERENCE, Node.THRESHOLD,
534 def addOutput(self, name, algorithm, annotations={}, attributes={}):
536 Adds a sub output element with name and algorithm
539 return HanOutput.addOutput(self.
root_output_level, name, algorithm, annotations, attributes)
546 retrieves the algorithm han object associated with name
555 retrieves the han reference associated with name
567 Add a DQParameter object to a HanDocument, Doing this it creates the tree of
571 if dqparameter.type !=
"DQParameter":
573 "Object: "+
str(dqparameter)+
" type does not match 'DQParameter'")
575 histoname = dqparameter.getInput().
split(
'/')
578 for directory
in histoname[0:len(histoname)-1]:
579 subdir = theDir.getSubDir(directory)
581 subdir = theDir.addSubDir(directory)
584 algo = dqparameter.getAlgorithm()
586 raise Exception(
'DQParameter without DQAlgorithm')
587 dqalgoname, dqalgolibrary = algo.id, algo.getLibraryName()
589 dqrefname, dqreference, refs =
"", dqparameter.getReference(), []
590 if dqreference != [
None]:
591 refs =
'[%s]' % (
','.
join(_.id
for _
in dqreference))
592 for iref
in dqreference:
595 if handocument.getReference(ref)
is None:
597 refcompletename = iref.getReference()
598 filename = refcompletename.rpartition(
':')[0]
599 refhistoname = refcompletename.rpartition(
':')[
602 ref, histogramname=refhistoname, file=filename,
603 info=iref.getAnnotation(
'info'))
604 handocument.appendChild(hanref)
609 warnings = toList(dqparameter.getWarnings())
610 errors = toList(dqparameter.getErrors())
611 thresholds, hanthreshold, thresholdsname =
'',
None,
''
612 if (warnings != [
None])
and (errors != [
None]):
614 thresholds = dqparameter.id.replace(
615 '_',
'__').
replace(
'/',
'_')+
'_thr'
617 thresholdsname = thresholds
618 thresholds =
'_'+thresholds
620 def getCorrespondingRed(warningname):
622 if e.getAttribute(
'Name')[1] == warningname:
625 for warning
in warnings:
626 warningname = warning.getAttribute(
'Name')[1]
627 error = getCorrespondingRed(warningname)
630 'Cannot find corresponding error for warning names: '+warning.id)
631 hanthreshold.addLimit(warningname, warning.getAttribute(
632 'Value')[1], error.getAttribute(
'Value')[1])
634 handocument.appendChild(hanthreshold)
637 parameterstr =
'_'.
join([x.id
for x
in toList(
638 dqparameter.getAlgorithmParameters())
if x
is not None])
640 for x
in toList(dqparameter.getAlgorithmParameters()):
643 parameters[x.getName()[1]] = x.getValue()[1][0]
645 hanalgoname = (
"%s_%s%s%s%s" % (dqalgolibrary, dqalgoname,
646 dqrefname, thresholds.replace(
'/',
'_'), parameterstr))
648 theDir.addHistogram(histogram=histoname[len(histoname)-1], algorithm=hanalgoname,
649 annotations=dqparameter.getAllAnnotations(), output=output, attributes=dqparameter.getAllAttributes())
651 if handocument.getAlgorithm(hanalgoname)
is None:
653 node =
HanAlgorithm(name=hanalgoname, algoname=dqalgoname, libname=dqalgolibrary,
654 reference=refs, thresholds=thresholdsname, parameters=parameters)
655 handocument.appendChild(node)
657 compalg = algo.getCompositeAlgorithm()
658 if compalg
is not None:
660 libnames=compalg.getLibNames())
661 handocument.appendChild(node)
662 except Exception
as msg:
664 "Object: "+
str(dqparameter)+
" is not a valid DQParameter. Reason: "+
str(msg))
675 This helper return the list of objects that are the roots in the tree represented by input.
680 if o.type == objecttype:
681 if len(o.isReferencedBy) == 0:
685 "object %s is not a valid DQBase object" % o)
696 This returns all DQBase objects reachable from the rootlist as a set.
703 if isinstance(dqbase, list):
705 if not isinstance(dqbase, DQBase):
707 '%s is not a valid DQBase object; this should never happen' % dqbase)
709 for rel
in dqbase.getAllRelatedObjects():
714 for dqbase
in toList(rootlist):
724 Writes the configuration to a han file.
725 The configuration has to be passed as a list of roots in han configuration.
729 for element
in configList:
731 if not DQHanConfMaker._isAceptedHanElement(element):
732 print(
"==========WARNING===========")
735 " does not have a valid han representation, cannot save")
736 print(
"The object is referenced by:", element.isReferencedBy)
737 print(
"You may need to manually edit the configuration")
738 print(
"============================")
739 configList.remove(element)
741 print(element.isReferencedBy)
749 def _addchild(hanfather, dqregion, handocument):
750 outputalgo = dqregion.getAlgorithm()
751 if handocument.getAlgorithm(outputalgo.id)
is None:
756 outputalgo.id, outputalgo.id, outputalgo.getLibraryName()))
757 output = hanfather.addOutput(dqregion.id, outputalgo.id, annotations=dqregion.getAllAnnotations(
758 ), attributes=dqregion.getAllAttributes())
760 for subregion
in dqregion.getSubRegions():
761 if subregion
is not None:
762 _addchild(output, subregion, doc)
764 for parameter
in dqregion.getDQParameters():
765 if parameter
is not None:
767 output=output.getOutputPath())
769 for region
in rootregions:
770 _addchild(doc, region, doc)
772 fileout =
open(filename,
'w')
773 print(doc.toprettyhan(
" "), file=fileout)