From f9920bb59e50c803a6b1e5b1011e676e4710076c Mon Sep 17 00:00:00 2001 From: Tim Adye <Tim.Adye@cern.ch> Date: Wed, 11 Apr 2018 18:04:26 +0100 Subject: [PATCH] Pull recent changes from SVN trunk (also tagged DCubeClient-00-00-52) Updates from ChangeLog: 2017-07-10 Tim Adye <T.J.Adye@rl.ac.uk> * Add support for TEfficiency plots (plotted as "graph" type) * fix graph statistics display and show y-mean/RMS instead of x-mean/RMS for 1D * don't crash on empty graph * graph plot style more like hist1d (red full circle, full-size plot, better ranges) M python/DCubeConfig.py M python/DCubeTester.py M python/DCubePlotter.py 2017-03-26 Peter Sherwood <peter@MacBook-Pro-7.fritz.box> * share/DCubeValid.xml: added new branch regex fo NN.N (eg 21.0) new cmtconfigs x86_64-slc6-gcc62-(opt, dev), new project Athena 2016-04-09 Atlas-Validation Runtimetester <rtt@lxplus0003.cern.ch> * Tagging DCubeClient-00-00-51 * Python 2.7.10 and ROOT 6.06/02 version update in dev nightly branch breaks the code to fetch histograms from a TFile instance, as the TFile.Get() function no longer accepts a unicode path, it needs ascii. Fixed by converting path to path.encode('ascii', 'ignore'). M python/DCubeTester.py M python/DCubeApp.py Former-commit-id: e45e8ee6212d7a75a6699633b2743ab4201d9b6b --- Tools/DCubeClient/python/DCubeApp.py | 220 ++++++++-------- Tools/DCubeClient/python/DCubeConfig.py | 2 +- Tools/DCubeClient/python/DCubeOptParser.py | 6 + Tools/DCubeClient/python/DCubePlotter.py | 186 ++++++------- Tools/DCubeClient/python/DCubeTester.py | 290 +++++++++++++-------- Tools/DCubeClient/share/DCubeValid.xml | 19 +- 6 files changed, 382 insertions(+), 341 deletions(-) diff --git a/Tools/DCubeClient/python/DCubeApp.py b/Tools/DCubeClient/python/DCubeApp.py index 9d510aae51a9..9cee9b55210f 100644 --- a/Tools/DCubeClient/python/DCubeApp.py +++ b/Tools/DCubeClient/python/DCubeApp.py @@ -14,7 +14,7 @@ from DCubeTester import DCubeTester from DCubePHPWriter import DCubePHPWriter import unittest ## -# @class DCubeApp +# @class DCubeApp # @author Krzysztof Daniel Ciba (Krzysztof.Ciba@NOSPAMgmail.com) # @brief DCube client application class DCubeApp( DCubeObject ): @@ -25,7 +25,7 @@ class DCubeApp( DCubeObject ): ## left over positional arguments as list args = None - ## path to monitored root file + ## path to monitored root file monitoredURI = None ## path to reference root file @@ -46,15 +46,15 @@ class DCubeApp( DCubeObject ): import ROOT global ROOT - + monitoredURI = None if ( len(self.args) == 2 ): - self.monitoredURI = self.args[-1] - + self.monitoredURI = self.args[-1] + DCubeLogger( self.opts.log, logName="", toConsole=True ) super( DCubeApp, self ).__init__( self ) - + ## DCubeVersion instance theVersion = DCubeVersion() @@ -62,11 +62,11 @@ class DCubeApp( DCubeObject ): self.info( theVersion.python() ) self.info( theVersion.root() ) - + ## DCubeValid instance self.valid = DCubeValid() - - for line in str(self.valid).split("\n"): + + for line in str(self.valid).split("\n"): self.info( line ) self.__dumpOptions() @@ -86,7 +86,7 @@ class DCubeApp( DCubeObject ): self.info("*** SUCCESS ***") sys.exit(0) - elif ( self.opts.config and self.monitoredURI ): + elif ( self.opts.config and self.monitoredURI ): self.info("RUN: test suite execution") @@ -94,7 +94,7 @@ class DCubeApp( DCubeObject ): runConfig = dcubeConfig.getConfig( strict = False ) #if ( not runConfig ): # runConfig = dcubeConfig.getConfig( strict = False ) - + if ( self.monitoredURI ): if ( self.exists( self.monitoredURI ) ): @@ -103,9 +103,9 @@ class DCubeApp( DCubeObject ): self.error("monitored root file %s not found" % self.monitoredURI ) else: raise DCubeException( "wrong arguments, monitored file not specified!" ) - + if ( runConfig ): - + if ( self.runConfig ( runConfig ) ): if ( self.tester ): @@ -125,7 +125,7 @@ class DCubeApp( DCubeObject ): else: self.error( "wrong set of CLI options, neither generation of config (-g) nor test suite excecution (-c CONFIG.XML MONITORED.root) specified" ) sys.exit(-1) - + except DCubeException, value: self.epanic( value ) self.epanic("*** FAILURE ***") @@ -138,31 +138,31 @@ class DCubeApp( DCubeObject ): self.info("will run test suite using xml configuration..." ) ## output XML DOM document - self.xmldoc = xml.dom.minidom.Document() + self.xmldoc = xml.dom.minidom.Document() self.xmldoc.appendChild( xmlConfig ) ## overwritting xml config to match run config self.debug("will overwrite xml config to match run config...") - xmlConfig.setAttribute( "branch", self.opts.branch ) + xmlConfig.setAttribute( "branch", self.opts.branch ) xmlConfig.setAttribute( "install", self.opts.install ) xmlConfig.setAttribute( "cmtconfig", self.opts.cmtconfig ) xmlConfig.setAttribute( "project", self.opts.project ) xmlConfig.setAttribute( "jobId", self.opts.jobId ) self.debug("done!") - config = "/".join( [ xmlConfig.getAttribute( "branch" ), - xmlConfig.getAttribute( "install" ), - xmlConfig.getAttribute( "cmtconfig" ), - xmlConfig.getAttribute( "project" ), - xmlConfig.getAttribute( "jobId" ) ] ) - self.debug( "the run config is %s" % config ) + config = "/".join([xmlConfig.getAttribute("branch"), + xmlConfig.getAttribute("install"), + xmlConfig.getAttribute("cmtconfig"), + xmlConfig.getAttribute("project"), + xmlConfig.getAttribute("jobId")]) + self.debug("the run config is %s" % config) ## get pvalue limits - pvalues = xmlConfig.getElementsByTagName( "plimit" ) - if ( len(pvalues) == 0 ): + pvalues = xmlConfig.getElementsByTagName("plimit") + if len(pvalues) == 0: self.warn("tag <plimit> not found, will use CLI pvalue limits FAIL=%f WARN=%f" % ( self.opts.pfail, self.opts.pwarn ) ) - elif ( len(pvalues) > 1 ): + elif len(pvalues) > 1: self.warn("too many <plimit> tags, will use CLI pvalue limits FAIL=%f WARN=%f" % ( self.opts.pfail, self.opts.pwarn ) ) else: @@ -181,11 +181,11 @@ class DCubeApp( DCubeObject ): referenceNode = None self.referenceURI = None - ## reference root file + ## reference root file if ( self.opts.reference != None ): self.referenceURI = os.path.abspath( self.opts.reference ) - + self.debug("will use reference root file from CLI = %s" % self.referenceURI ) referenceNode = self.xmldoc.createElement( "reference" ) referenceNode.setAttribute( "file", self.referenceURI ) @@ -204,7 +204,7 @@ class DCubeApp( DCubeObject ): referenceNode = reference[0] self.referenceURI = os.path.abspath( referenceNode.getAttribute("file") ) self.__update( "reference", self.referenceURI ) - + self.debug("will use reference root file from XML = %s" % self.referenceURI ) # monitored root file @@ -215,7 +215,7 @@ class DCubeApp( DCubeObject ): # date node dateNode = self.xmldoc.createElement( "date" ) - dateCDataNode = self.xmldoc.createTextNode( self.opts.isodate ) + dateCDataNode = self.xmldoc.createTextNode( self.opts.isodate ) dateNode.appendChild( dateCDataNode ) @@ -227,18 +227,18 @@ class DCubeApp( DCubeObject ): self.__update("output", self.opts.monitored + ".dcube.xml" ) # get <tdirectory> tags and run tester - tdirs = xmlConfig.getElementsByTagName( "TDirectory" ) + tdirs = xmlConfig.getElementsByTagName( "TDirectory" ) if ( len(tdirs) == 0 ): raise DCubeException("no <TDirectory> tags found!") else: ## DCubeTester instance self.tester = DCubeTester( self.xmldoc, self.parsed ) - + self.refTFile = None - if ( self.exists( self.referenceURI ) ): + if self.exists(self.referenceURI): try: - self.refTFile = ROOT.TFile.Open( self.referenceURI, "READ" ) + self.refTFile = ROOT.TFile.Open(self.referenceURI, "READ") except Exception, value: - self.epanic( "cannot get handle for referece root file, all tests will be skipped, reason: %s" % str(value) ) + self.epanic( "cannot get handle for reference root file, all tests will be skipped, reason: %s" % str(value) ) else: self.warn("reference root file not exists, all tests will be skipped!") @@ -247,24 +247,24 @@ class DCubeApp( DCubeObject ): try: self.monTFile = ROOT.TFile.Open( self.monitoredURI , "READ") except Exception, value: - msg = "cannot get handle for monitored root file, reason: %s" % str(value) + msg = "cannot get handle for monitored root file, reason: %s" % str(value) raise DCubeException( msg ) else: raise DCubeException( "monitored root file %s not exists!" % self.monitoredURI ) - + # run DCubeTester recursively - self.test( tdirs[0], tdirs[0].getAttribute("name") ) + self.test( tdirs[0], tdirs[0].getAttribute("name") ) if ( self.refTFile ): self.refTFile.Close() if ( self.monTFile ): self.monTFile.Close() - # print and append summary node + # print and append summary node xmlConfig.appendChild ( self.tester.summary() ) - + # save output XML to file return self.__save( ) - - + + ## get CDATA section # @param self "Me, myself and Irene" # @param nodelist list of XML DOM Node objects @@ -273,67 +273,67 @@ class DCubeApp( DCubeObject ): for node in nodelist: if node.nodeType == node.TEXT_NODE: out = out + node.data - return out - + return out + ## main worker here # @param self "Me, myself and Irene" # @param node xml \<tdirectory\> node # @param path full path inside both root files - def test( self, node, path ): - - self.debug("now testing objects in path = %s" % path ) - - status = [ ] + def test(self, node, path): + self.debug("now testing objects in path = %s" % path) + status = [] for child in node.childNodes: - - if ( child.nodeType == node.ELEMENT_NODE ): - self.debug("child tagName %s" % child.tagName ) + if child.nodeType == node.ELEMENT_NODE: + self.debug("child tagName %s" % child.tagName) tagName = child.tagName - if ( tagName == "TDirectory" ): - status.append ( self.test( child, os.path.join( path , child.getAttribute("name") ) ) ) - - for test in [ "KS", "chi2", "bbb" ]: - for stat in [ "OK", "WARN", "FAIL" ]: + if tagName == "TDirectory": + status.append(self.test(child, os.path.join(path, child.getAttribute("name")))) + + for test in ["KS", "chi2", "bbb"]: + for stat in ["OK", "WARN", "FAIL"]: attr = test + stat - - parentCounter = node.getAttribute( attr ) - if ( not parentCounter ): parentCounter = "0" - - nodeCounter = child.getAttribute( attr ) - if ( not nodeCounter ): nodeCounter = "0" - - node.setAttribute( attr, "%d" % ( int(parentCounter) + int(nodeCounter) ) ) + + parentCounter = node.getAttribute(attr) + if not parentCounter: + parentCounter = "0" + + nodeCounter = child.getAttribute(attr) + if not nodeCounter: + nodeCounter = "0" + + node.setAttribute(attr, "%d" % (int(parentCounter) + int(nodeCounter))) else: - if ( child.hasAttribute("name") ): - objName = child.getAttribute( "name" ) - objTests = child.getAttribute( "tests" ).split(",") - self.debug( "found type=%s name=%s tests=%s in path %s" % ( tagName, objName, str(objTests), path ) ) - - if ( path == "/" ): + if child.hasAttribute("name"): + objName = child.getAttribute("name") + objTests = child.getAttribute("tests").split(",") + self.debug("found type=%s name=%s tests=%s in path %s" % (tagName, objName, str(objTests), path)) + + if path == "/": objPath = objName else: - objPath = os.path.join( path, objName ) - - refObj = self.refTFile.Get( objPath ) - monObj = self.monTFile.Get( objPath ) - - status.append( self.tester.test( child, monObj, refObj ) ) + objPath = os.path.join(path, objName) + + objPath = objPath.encode('ascii', 'ignore') + + refObj = self.refTFile.Get(objPath) + monObj = self.monTFile.Get(objPath) + + status.append(self.tester.test(child, monObj, refObj)) else: - self.warn( "empty attribute 'name' found for tag <%s> in path %s, skipping!" % ( tagName, path ) ) - - statusAttr = "OK" - if ( ( "FAIL" in status ) or - ( None in status ) ): - statusAttr = "FAIL" - elif ( "WARN" in status ): - statsuAttr = "WARN" - - self.debug("TDirectory %s status %s" % ( path, statusAttr ) ) - node.setAttribute( "status", statusAttr ) - - return statusAttr - + self.warn("empty attribute 'name' found for tag <%s> in path %s, skipping!" % (tagName, path)) + + statusAttr = "OK" + if (("FAIL" in status) or (None in status)): + statusAttr = "FAIL" + elif "WARN" in status: + statusAttr = "WARN" + + self.debug("TDirectory %s status %s" % (path, statusAttr)) + node.setAttribute("status", statusAttr) + + return statusAttr + ## update parsed options from DCubeOptParser # @param self "Me, myself and Irene" # @param key option name @@ -341,7 +341,7 @@ class DCubeApp( DCubeObject ): def __update( self, key, what ): self.debug("updating option %s to %s" % ( str(key), str(what) ) ) self.opts._update_loose( { key : what } ) - + ## dump left arguments to logger # @param self "Me, myself and Irene" def __dumpArgs( self ): @@ -361,17 +361,17 @@ class DCubeApp( DCubeObject ): if ( v == "" ): v = "not set" self.info("[%02d] %s %s" % ( i, k, v)) i += 1 - + ## save new output XML to file # @param self "Me, myself and Irene" def __save( self ): - + outputURI = os.path.abspath( self.opts.output ) self.__backup( outputURI ) try: fileXML = open( outputURI, "w+") self.xmldoc.normalize() - + xmlstring = self.xmldoc.toprettyxml(" ", "\n").split("\n") for line in xmlstring: if line.strip("\n").strip() != "": @@ -405,8 +405,8 @@ class DCubeApp( DCubeObject ): except OSError, value: msg = "creation of backup file %s failed - %s" % ( backupURI, str(value) ) self.epanic( msg ) - - ## check existence of file + + ## check existence of file # @param self "Me, myself and Irene" # @param filename a file name to check def exists( self, filename ): @@ -417,23 +417,23 @@ class DCubeApp( DCubeObject ): ## produce PHP files # @param self "Me, myself and Irene" - # @return boolean status + # @return boolean status def __producePHPs( self ): self.info("will produce PHP files...") if ( not self.opts.server ): self.error("path to DCubeServer not set, PHP files won't be produced") return False - + if ( None not in ( self.opts.log, self.opts.config, self.opts.output ) ): phpWriter = DCubePHPWriter( self.parsed ) phpURI = os.path.abspath( self.opts.output + ".php" ) logURI = os.path.abspath( os.path.join( os.path.dirname(self.opts.output), "dcubelog.php" ) ) - + self.debug( "out php URI %s" % phpURI ) self.debug( "log php URI %s" % logURI ) - + phpOK = False try: filePHP = open( phpURI, "w+" ) @@ -457,15 +457,15 @@ class DCubeApp( DCubeObject ): return ( phpOK and logOK ) - ## main comment in output XML file + ## main comment in output XML file # @param self "Me, myself and Irene" # @return a comment string def __mainXMLComment( self ): pass - -## -# @class test_DCubeApp + +## +# @class test_DCubeApp # @author Krzysztof Daniel Ciba (Krzysztof.Ciba@NOSPAMgmail.com) # @brief test case for DCubeApp # @todo cover more! @@ -481,10 +481,10 @@ class test_DCubeApp( unittest.TestCase ): "--jobId", "job_1", "--server", "/afs/cern.ch/user/c/cibak/scratch1/dcube/dcube.php", "monitored.root" ] - + self.sysExitHolder = sys.exit def exitCode( value ): - print "sys.exit called with value %s" % str(value) + print "sys.exit called with value %s" % str(value) sys.exit = exitCode ## test contructor @@ -501,12 +501,12 @@ class test_DCubeApp( unittest.TestCase ): theApp = DCubeApp( ) del theApp - + ## test suite execution if __name__ == "__main__": - + # sometimes I believe python interpreter ignores all my comments testLoader = unittest.TestLoader() - suite = testLoader.loadTestsFromTestCase(test_DCubeApp) + suite = testLoader.loadTestsFromTestCase(test_DCubeApp) unittest.TextTestRunner(verbosity=3).run(suite) - + diff --git a/Tools/DCubeClient/python/DCubeConfig.py b/Tools/DCubeClient/python/DCubeConfig.py index 49cf93372345..ea6823881d40 100644 --- a/Tools/DCubeClient/python/DCubeConfig.py +++ b/Tools/DCubeClient/python/DCubeConfig.py @@ -539,7 +539,7 @@ class DCubeConfig( DCubeUtils.DCubeObject ): else: self.warn("dimension > 2 for histogram '%s', skipping" % fp) - elif ( isa.InheritsFrom("TGraph") ): + elif ( isa.InheritsFrom("TGraph") or isa.InheritsFrom("TEfficiency") ): self.debug( nbsp + " --> found object '%s' at location '%s' of name '%s'" % ( cl, path, name) ) diff --git a/Tools/DCubeClient/python/DCubeOptParser.py b/Tools/DCubeClient/python/DCubeOptParser.py index b93915aa9be1..8f5b530b7bd2 100644 --- a/Tools/DCubeClient/python/DCubeOptParser.py +++ b/Tools/DCubeClient/python/DCubeOptParser.py @@ -163,6 +163,11 @@ class DCubeOptParser( object ): help="batch mode for PyROOT [always on]") + self.__par.add_option( "--useVarNameForPlotName", + action="store_true", + dest="useVarNameForPlotName", + help="Name output plots after the variable they contain [default: use a generated UUID as name]") + self.__par.set_defaults( pwarn=0.95, pfail=0.75, config="dcube_config.xml", @@ -178,6 +183,7 @@ class DCubeOptParser( object ): jobId="*", generate=False, makeplots=False, + useVarNameForPlotName=False, root2null=False) diff --git a/Tools/DCubeClient/python/DCubePlotter.py b/Tools/DCubeClient/python/DCubePlotter.py index 0f3f4ea64bd3..cbb1016cfb8c 100644 --- a/Tools/DCubeClient/python/DCubePlotter.py +++ b/Tools/DCubeClient/python/DCubePlotter.py @@ -153,7 +153,10 @@ class DCubePlotter( DCubeObject ): ## get unique plot name # @param self "Me, myself and Irene" def __plotName( self, what="" ): - return what + "_" + str(uuid.uuid4()) + ".png" + name = str(uuid.uuid4()) + if self.opts.useVarNameForPlotName: + name = self.name + return what + "_" + name + ".png" ## plot dispatcher # @param self "Me, myself and Irene" @@ -178,10 +181,11 @@ class DCubePlotter( DCubeObject ): #self.debug("additional plot options are: '%s'" % str(plotOpts) ) for opt in plotOpts: - if ( opt not in [ "logx", "logy", "logz", "norm" ] ): + if ( opt not in [ "logx", "logy", "logz", "norm", "enorm" ] ): self.error("ignoring unknown additional plot option '%s'" % opt ) else: self.plotOpts.append(opt) + if opt == "enorm": self.plotOpts.append("norm") self.debug("additional plot options are: '%s'" % str(plotOpts) ) @@ -260,6 +264,9 @@ class DCubePlotter( DCubeObject ): status = [ "OK" ] self.debug("plotting %s of type %s" % ( self.name, self.className ) ) + title = "%s;%s;%s" % ( self.mon.GetTitle(), + self.mon.GetXaxis().GetTitle(), + self.mon.GetYaxis().GetTitle() ) graph = ROOT.TMultiGraph() canvas = self.__getCanvas() @@ -267,17 +274,22 @@ class DCubePlotter( DCubeObject ): xmin, xmax, ymin, ymax = self.__getMinMaxTGraph( self.mon, self.ref ) - dx = abs(xmax - xmin) * 0.15 dy = abs(ymax - ymin) + y0 = ymin - dy * 0.1 + if ymin >= 0.0 and y0 < 0.0: y0 = 0.0 + ymin= y0 + ymax = ymax + dy * (self.unzoom-1.0) - ROOT.gPad.DrawFrame( xmin - dx, ymin - dy * 0.4, xmax + dx, ymax + dy*self.unzoom) + ROOT.gPad.DrawFrame( xmin, ymin, xmax, ymax, title) - ROOT.gStyle.SetPadBottomMargin(0.2) +## remove unneeded padding (10/7/2017) +# ROOT.gStyle.SetPadBottomMargin(0.2) + self.mon.SetMarkerStyle( ROOT.kFullCircle ) self.mon.SetMarkerColor( ROOT.kRed ) self.mon.SetFillColor( ROOT.kRed ) - self.mon.SetFillStyle( 3005 ) + self.mon.SetFillStyle( 3004 ) self.mon.SetLineColor( ROOT.kRed ) @@ -287,7 +299,7 @@ class DCubePlotter( DCubeObject ): self.ref.SetMarkerColor( ROOT.kBlue ) self.ref.SetMarkerSize( 1.0 ) self.ref.SetFillColor( ROOT.kBlue ) - self.ref.SetFillStyle( 3004 ) + self.ref.SetFillStyle( 3005 ) self.ref.SetLineColor( ROOT.kBlue ) graph.Add( self.ref, "P" ) @@ -339,19 +351,15 @@ class DCubePlotter( DCubeObject ): diffGraph.SetPoint(i, x, points[x] ) i += 1 - xl = xmin - dx - xr = xmax + dx - xmin, xmax, ymin, ymax = self.__getMinMaxTGraph( diffGraph ) dy = abs(ymax - ymin) - - if ( ymin > ymax ): - a = ymin - ymin = ymax - ymax = ymin + y0 = ymin - dy * 0.1 + if ymin >= 0.0 and y0 < 0.0: y0 = 0.0 + ymax = ymax * self.unzoom + if ( ymax == 0.0 ): ymax = ymin + ( abs(ymin) * self.unzoom ) - ROOT.gPad.DrawFrame( xl, ymin - (dy * 0.4), xr, ymax + (dy*self.unzoom) ) + ROOT.gPad.DrawFrame( xmin, y0, xmax, ymax, "diff %s" % title) diffGraph.SetTitle( self.mon.GetTitle() ) diffGraph.SetName( self.mon.GetName() ) @@ -372,106 +380,66 @@ class DCubePlotter( DCubeObject ): # @param self "Me, myself and Irene" def __getMinMaxTGraph( self, mon=None, ref=None ): - xmin = xmax = ymin= ymax = None - if ( mon ): - x = ROOT.Double(0) - y = ROOT.Double(0) - - exl = ROOT.Double(0) - exr = ROOT.Double(0) - eyl = ROOT.Double(0) - eyh = ROOT.Double(0) - - if ( self.className == "TGraph" ): - - for i in range( mon.GetN() ): - - mon.GetPoint(i, x, y) - - if ( xmin == None ): xmin = ROOT.Double(x) - if ( xmax == None ): xmax = ROOT.Double(x) - if ( ymin == None ): ymin = ROOT.Double(y) - if ( ymax == None ): ymax = ROOT.Double(y) - - if ( x < xmin ): xmin = x - if ( x > xmax ): xmax = x - if ( y < ymin ): ymin = y - if ( y > ymax ): ymax = y - - if ( ref ): - for i in range( ref.GetN() ): - - ref.GetPoint(i, x, y) - - if ( xmin == None ): xmin = ROOT.Double(x) - if ( xmax == None ): xmax = ROOT.Double(x) - if ( ymin == None ): ymin = ROOT.Double(y) - if ( ymax == None ): ymax = ROOT.Double(y) - - if ( x < xmin ): xmin = x - if ( x > xmax ): xmax = x - if ( y < ymin ): ymin = y - if ( y > ymax ): ymax = y - else: - - for i in range( mon.GetN() ): - - mon.GetPoint(i, x, y) - - exl = mon.GetErrorXhigh( i ) - exr = mon.GetErrorXlow( i ) - eyh = mon.GetErrorYhigh( i ) - eyl = mon.GetErrorYlow( i ) + xmin = xmax = ymin = ymax = exmin = exmax = dxmin = None + xd = ROOT.Double(0) + yd = ROOT.Double(0) + for g in (ref, mon): + if g: + x0 = None + for i in range( g.GetN() ): + + g.GetPoint(i, xd, yd) + x = float(xd) + y = float(yd) + + if x0 is not None: + dx = x - x0 + if dx > 0.0 and (dxmin is None or dx < dxmin): dxmin = dx + x0 = x + + if ( self.className == "TGraph" ): + exh = exl = eyh = eyl = 0.0 + else: + exh = g.GetErrorXhigh( i ) + exl = g.GetErrorXlow( i ) + eyh = g.GetErrorYhigh( i ) + eyl = g.GetErrorYlow( i ) - xl = x - exr - xr = x + exl - yl = y - eyl + xh = x + exh + xl = x - exl yh = y + eyh + yl = y - eyl - if ( xmin == None ): xmin = ROOT.Double(xl) - if ( xmax == None ): xmax = ROOT.Double(xr) - if ( ymin == None ): ymin = ROOT.Double(yl) - if ( ymax == None ): ymax = ROOT.Double(yh) - - if ( xl < xmin ): xmin = xl - if ( xr > xmax ): xmax = xr - if ( yl < ymin ): ymin = yl - if ( yh > ymax ): ymax = yh - - if ( ref ): - - for i in range( ref.GetN() ): - - ref.GetPoint(i, x, y) - - exl = ref.GetErrorXhigh( i ) - exr = ref.GetErrorXlow( i ) - eyh = ref.GetErrorYhigh( i ) - eyl = ref.GetErrorYlow( i ) - - xl = x - exr - xr = x + exl - yl = y - eyl - yh = y + eyh - - if ( xmin == None ): xmin = ROOT.Double(xl) - if ( xmax == None ): xmax = ROOT.Double(xr) - if ( ymin == None ): ymin = ROOT.Double(yl) - if ( ymax == None ): ymax = ROOT.Double(yh) - - if ( xl < xmin ): xmin = xl - if ( xr > xmax ): xmax = xr - if ( yl < ymin ): ymin = yl - if ( yh > ymax ): ymax = yh - - - return ( xmin, xmax, ymin, ymax) + if ( xmin is None or xl < xmin ): xmin, exmin = xl, exl + if ( xmax is None or xh > xmax ): xmax, exmax = xh, exh + if ( ymin is None or yl < ymin ): ymin = yl + if ( ymax is None or yh > ymax ): ymax = yh + + # if no x-errors, add half-bin width + if ( dxmin is not None ): + if ( exmin <= 0.0 ): xmin -= 0.5 * dxmin + if ( exmax <= 0.0 ): xmax += 0.5 * dxmin + + # if no limits, then use graph range + if ref: g = ref + else: g = mon + if g: + if ( xmin is None or xmin >= xmax ): xmin = g.GetHistogram().GetXaxis().GetXmin() + if ( xmax is None or xmin >= xmax ): xmax = g.GetHistogram().GetXaxis().GetXmax() + if ( ymin is None or ymin >= ymax ): ymin = g.GetHistogram().GetYaxis().GetXmin() + if ( ymax is None or ymin >= ymax ): ymax = g.GetHistogram().GetYaxis().GetXmax() + + return ( xmin, xmax, ymin, ymax) def __normTH( self, obj=None ): if ( obj ): - self.debug( "will normalize histogram '%s'" % obj.GetName()) - integral = obj.Integral() + if ( "enorm" in self.plotOpts ): + self.debug( "will normalize histogram '%s' to the number of entries" % obj.GetName()) + integral = obj.GetEntries() + else: + self.debug( "will normalize histogram '%s'" % obj.GetName()) + integral = obj.Integral() if ( integral != 0.0 ): scale = 1.0 / integral self.debug("integral = %f, scale = %f" % (integral, scale ) ) diff --git a/Tools/DCubeClient/python/DCubeTester.py b/Tools/DCubeClient/python/DCubeTester.py index 943cdc3c5fd1..154101899b42 100644 --- a/Tools/DCubeClient/python/DCubeTester.py +++ b/Tools/DCubeClient/python/DCubeTester.py @@ -11,17 +11,18 @@ from DCubeUtils import DCubeObject, DCubeException from DCubePlotter import DCubePlotter import ROOT import unittest +import math ## # @class DCubeTester # @author Krzysztof Daniel Ciba (Krzysztof.Ciba@NOSPAMgmail.com) -# @brief perform statictics tests and plotting +# @brief perform statictics tests and plotting class DCubeTester( DCubeObject ): ## XML DOM Document instance xmldoc = None - ## XML DOM Element instance + ## XML DOM Element instance node = None ## handle for monitored root object @@ -35,7 +36,7 @@ class DCubeTester( DCubeObject ): ## intarnal histogram counter __nbObjs = 0 - + ## statistics summary table sumTable = { "KS" : { "OK" : 0, "WARN" : 0, @@ -57,15 +58,15 @@ class DCubeTester( DCubeObject ): 2 : "there is bin in ref hist with low then 1 exp number of event", 3 : "there are bins in both histograms with less than 1 event" } - + ## summary status __status = "" - + ## c'tor # @param self "Me, myself and Irene" # @param xmldoc XML DOM Document instance def __init__( self, xmldoc, parsed ): - + super( DCubeTester, self ).__init__( self ) self.xmldoc = xmldoc self.opts, self.args = parsed @@ -73,22 +74,21 @@ class DCubeTester( DCubeObject ): "bbb" : self.__testBBB, "chi2" : self.__testChi2, "meanY": self.__testMeanY } - + if ( self.opts.makeplots ): self.info("will produce plot files") self.__plotter = DCubePlotter( xmldoc, parsed ) else: self.warn("making of plots disabled") - - ## + + ## # @param self "Me, myself and Irene" - # @param node DOM XML node + # @param node DOM XML node # @param mon monitored ROOT object # @param ref reference ROOT object - # @return modified XML node - def test( self, node, mon=None, ref=None ): - + # @return modified XML node + def test(self, node, mon=None, ref=None): self.__nbObjs += 1 self.node = self.mon = self.ref = None @@ -100,29 +100,28 @@ class DCubeTester( DCubeObject ): self.ref = ref # mon exists? - if ( not self.mon ): + if not self.mon: status = "FAIL;monitored not found" - self.node.setAttribute( "status", status ) + self.node.setAttribute("status", status) if status not in self.errors.keys(): - self.errors[ status ] = 1 + self.errors[status] = 1 else: - self.errors[ status ] = self.errors[ status ] + 1 + self.errors[status] = self.errors[status] + 1 self.error("monitored object not found!") return "FAIL" - cl = self.mon.Class().GetName() - isHist = False - if ( cl[:2] in ( "TH", "TP") ): isHist = True - + cl = self.mon.Class().GetName() + isHist = (cl[:2] in ("TH", "TP")) + # dimension OK? - if ( isHist and self.mon.GetDimension() > 2 ): + if (isHist and self.mon.GetDimension() > 2): status = "FAIL;unsupported object, dimension bigger than 2" - self.node.setAttribute( "status", status ) - if ( status not in self.errors.keys() ): - self.errors[ status ] = 1 + self.node.setAttribute("status", status) + if status not in self.errors.keys(): + self.errors[status] = 1 else: - self.errors[ status ] = self.errors[ status ] + 1 - self.error( "unsuported object found" ) + self.errors[status] = self.errors[status] + 1 + self.error("unsuported object found") return "FAIL" # reference exists? @@ -134,7 +133,7 @@ class DCubeTester( DCubeObject ): self.errors[ status ] = 1 else: self.errors[ status ] = self.errors[ status ] + 1 - + if ( self.mon and self.ref ): # same class? monClassName = self.mon.Class().GetName() @@ -152,44 +151,60 @@ class DCubeTester( DCubeObject ): if ( isHist ): - self.monBins = [ self.mon.GetNbinsX(), self.mon.GetNbinsY() ] + self.monBins = [ self.mon.GetNbinsX(), self.mon.GetNbinsY() ] if ( isHist and self.ref ): self.refBins = [ self.ref.GetNbinsX(), self.ref.GetNbinsY() ] - + if ( isHist and self.mon and self.ref ): # same binnig? monBins = [ "%s=%d" % ( x, y) for ( x, y) in zip(["x", "y"], self.monBins ) ] - refBins = [ "%s=%d" % ( x, y) for ( x, y) in zip(["x", "y"], self.refBins ) ] + refBins = [ "%s=%d" % ( x, y) for ( x, y) in zip(["x", "y"], self.refBins ) ] diffBins = [ "mon %s ref %s" % (x, y) for (x,y) in zip(monBins,refBins) if x != y ] if ( diffBins ): - status = "FAIL;different binnig" + status = "FAIL;different binning" self.node.setAttribute( "status", status + " %s" % " ".join(diffBins) ) if ( status not in self.errors.keys() ): self.errors[ status ] = 1 else: self.errors[ status ] = self.errors[ status ] + 1 self.error("different binning for mon and ref objects!") - return "FAIL" + return "FAIL" - status = "OK" + if cl == "TEfficiency": + # Replace with TGraphAsymmErrors for stats and plotting + self.mon = mon.CreateGraph("AP") + self.ref = ref.CreateGraph("AP") + # remove x-error bars + for i in range( self.mon.GetN() ): + self.mon.SetPointEXlow( i, 0.0 ) + self.mon.SetPointEXhigh( i, 0.0 ) + for i in range( self.ref.GetN() ): + self.ref.SetPointEXlow( i, 0.0 ) + self.ref.SetPointEXhigh( i, 0.0 ) + isHist = False + + status = "OK" if ( isHist ): status = self.__grabHistogramStat() else: - status = self.__grabGraphStat() + status = self.__grabGraphStat() plotStatus = "OK" if ( self.opts.makeplots ): - plotStatus = self.__makePlots() + plotStatus = self.__makePlots() else: plotStatus = "WARN;plots not reqested" self.node.setAttribute( "plots", plotStatus) return status - - ## grab statistic info for TGraphXXX + + ## grab statistic info for TGraphXXX # @param self "Me, myself and Irene" def __grabGraphStat( self ): + if self.mon.GetHistogram().GetDimension() == 1: axis = 2 # change to y-mean and y-RMS (10/7/2017) + else: axis = 1 # TGraph2D probably not supported anyway + statNode = self.xmldoc.createElement( "stat" ) self.node.appendChild( statNode ) @@ -200,15 +215,15 @@ class DCubeTester( DCubeObject ): nbPointsNode.appendChild( nbPointsCData ) meanNode = self.xmldoc.createElement( "mean" ) - meanCData = self.xmldoc.createTextNode( "%4.3f" % self.mon.GetMean() ) + meanCData = self.xmldoc.createTextNode( "%4.3f" % self.mon.GetMean(axis) ) if ( self.ref ): - meanNode.setAttribute( "ref" , "%4.3f" % self.ref.GetMean() ) + meanNode.setAttribute( "ref" , "%4.3f" % self.ref.GetMean(axis) ) meanNode.appendChild( meanCData ) rmsNode = self.xmldoc.createElement( "rms" ) - rmsCData = self.xmldoc.createTextNode( "%d" % self.mon.GetRMS() ) + rmsCData = self.xmldoc.createTextNode( "%4.3f" % self.mon.GetRMS(axis) ) if ( self.ref ): - rmsNode.setAttribute( "ref" , "%d" % self.ref.GetRMS() ) + rmsNode.setAttribute( "ref" , "%4.3f" % self.ref.GetRMS(axis) ) rmsNode.appendChild( rmsCData ) statNode.appendChild( nbPointsNode ) @@ -216,9 +231,9 @@ class DCubeTester( DCubeObject ): statNode.appendChild( rmsNode ) return "OK" - - - + + + ## grab basic statistics - nb of entries, mean and RMS # @param self "Me, myself and Irene" def __grabHistogramStat( self ): @@ -235,33 +250,54 @@ class DCubeTester( DCubeObject ): statNode.appendChild( entriesNode ) - dim = self.mon.GetDimension() + dim = self.mon.GetDimension() ### To dump MeanY values if ( "TProfile" in self.mon.Class().GetName() ): dim = 2 - # store under and overflows + # store under and overflows monU = [] monO = [] refU = [] refO = [] + #store underflows and overflows to check is some of them are inf or nan + vals = [] + if ( dim == 1 ): monU.append( self.mon.GetBinContent(0) ) + vals.append( self.mon.GetBinContent(0) ) monO.append( self.mon.GetBinContent( self.mon.GetNbinsX()+1 ) ) + vals.append( self.mon.GetBinContent( self.mon.GetNbinsX()+1 ) ) if ( self.ref ): refU.append( self.ref.GetBinContent(0) ) + vals.append( self.ref.GetBinContent(0) ) refO.append( self.ref.GetBinContent( self.ref.GetNbinsX()+1 ) ) + vals.append( self.ref.GetBinContent( self.ref.GetNbinsX()+1 ) ) elif ( dim == 2 ): monU.append( self.mon.GetBinContent( 0, 0 ) ) + vals.append( self.mon.GetBinContent( 0, 0 ) ) monO.append( self.mon.GetBinContent( self.mon.GetNbinsX()+1, 0 ) ) + vals.append( self.mon.GetBinContent( self.mon.GetNbinsX()+1, 0 ) ) monU.append( self.mon.GetBinContent( 0, self.mon.GetNbinsY()+1) ) - monO.append( self.mon.GetBinContent( self.mon.GetNbinsX()+1, self.mon.GetNbinsY()+1 ) ) + vals.append( self.mon.GetBinContent( 0, self.mon.GetNbinsY()+1) ) + monO.append( self.mon.GetBinContent( self.mon.GetNbinsX()+1, self.mon.GetNbinsY()+1 ) ) + vals.append( self.mon.GetBinContent( self.mon.GetNbinsX()+1, self.mon.GetNbinsY()+1 ) ) if ( self.ref ): refU.append( self.ref.GetBinContent( 0, 0 ) ) + vals.append( self.ref.GetBinContent( 0, 0 ) ) refO.append( self.ref.GetBinContent( self.ref.GetNbinsX()+1, 0 ) ) + vals.append( self.ref.GetBinContent( self.ref.GetNbinsX()+1, 0 ) ) refU.append( self.ref.GetBinContent( 0, self.ref.GetNbinsY()+1) ) - refO.append( self.ref.GetBinContent( self.ref.GetNbinsX()+1, self.ref.GetNbinsY()+1 ) ) + vals.append( self.ref.GetBinContent( 0, self.ref.GetNbinsY()+1) ) + refO.append( self.ref.GetBinContent( self.ref.GetNbinsX()+1, self.ref.GetNbinsY()+1 ) ) + vals.append( self.ref.GetBinContent( self.ref.GetNbinsX()+1, self.ref.GetNbinsY()+1 ) ) + + #check if some values are inf or nan + if ( self.__checkValues(vals) != "OK" ): + self.warn( "some values in histogram are infinity or NaN, skipping!") + self.node.setAttribute( "status", "FAIL;monitored or reference histogram contains inf or NaN values") + return "FAIL" underflowNode = self.xmldoc.createElement( "underflow" ) underflowCData = self.xmldoc.createTextNode( "%d" % sum( monU ) ) @@ -277,7 +313,7 @@ class DCubeTester( DCubeObject ): statNode.appendChild( underflowNode ) statNode.appendChild( overflowNode ) - + dimName = [ "x", "y", "z" ] for i in range( 1, dim+1 ): self.debug( "gathering statistics along %s axis" % dimName[i-1] ) @@ -285,7 +321,7 @@ class DCubeTester( DCubeObject ): dimNode = self.xmldoc.createElement( "dim" ) dimNode.setAttribute( "name", dimName[i-1] ) dimNode.setAttribute( "bins", "%d" % self.monBins[i-1]) - + underflowNode = self.xmldoc.createElement( "underflow" ) underflowCData = self.xmldoc.createTextNode( "%d" % monU[i-1] ) if ( self.ref ): @@ -293,7 +329,7 @@ class DCubeTester( DCubeObject ): underflowNode.appendChild( underflowCData ) dimNode.appendChild( underflowNode ) - + overflowNode = self.xmldoc.createElement( "overflow" ) overflowCData = self.xmldoc.createTextNode( "%d" % monO[i-1] ) if ( self.ref ): @@ -301,27 +337,27 @@ class DCubeTester( DCubeObject ): overflowNode.appendChild( overflowCData ) dimNode.appendChild( overflowNode ) - + meanNode = self.xmldoc.createElement( "mean" ) if ( self.ref ): meanNode.setAttribute( "ref", "%3.2e" % self.ref.GetMean(i) ) meanCData = self.xmldoc.createTextNode( "%3.2e" % self.mon.GetMean( i ) ) meanNode.appendChild( meanCData ) - + meanErrorNode = self.xmldoc.createElement( "mean_unc" ) if ( self.ref ): meanErrorNode.setAttribute( "ref", "%3.2e" % self.ref.GetMeanError(i) ) meanErrorCData = self.xmldoc.createTextNode( "%3.2e" % self.mon.GetMeanError( i ) ) meanErrorNode.appendChild( meanErrorCData ) - + rmsNode = self.xmldoc.createElement( "rms" ) if ( self.ref ): rmsNode.setAttribute( "ref", "%3.2e" % self.ref.GetRMS(i) ) rmsCData = self.xmldoc.createTextNode( "%3.2e" % self.mon.GetRMS(i) ) rmsNode.appendChild( rmsCData ) - + rmsErrorNode = self.xmldoc.createElement( "rms_unc" ) if ( self.ref ): rmsErrorNode.setAttribute( "ref", "%3.2e" % self.ref.GetRMSError(i) ) @@ -340,31 +376,52 @@ class DCubeTester( DCubeObject ): status = [ ] tests = [t for t in self.node.getAttribute('tests').strip().split(',') if t] - + + + if ( self.node.getAttribute('pwarn') ): + try: + pwarn = float ( self.node.getAttribute('pwarn').strip() ) + except TypeError, value: + raise DCubeException( "histogram %s pvalue limit for WARN is NAN" % self.node.getAttribute('name') ) + self.info("overriding pvalue limits for histogram %s: new WARN limit is pwarn=%s" % ( self.node.getAttribute('name'), pwarn ) ) + else: + pwarn = self.opts.pwarn + + if ( self.node.getAttribute('pfail') ): + try: + pfail = float ( self.node.getAttribute('pfail').strip() ) + except TypeError, value: + raise DCubeException( "histogram %s pvalue limit for FAIL is NAN" % self.node.getAttribute('name') ) + self.info("overriding pvalue limits for histogram %s: new FAIL limit is pfail=%s" % ( self.node.getAttribute('name'), pfail ) ) + else: + pfail = self.opts.pfail + + + if ( "all" in tests ): tests = [ "KS", "chi2", "bbb", "meany" ] if ( None not in ( self.mon, self.ref ) ): - + if ( "TProfile" in self.mon.Class().GetName() ): if ( "meany" in tests ): status.append( self.__testMeanY.__call__( statNode ) ) else: for test in tests: if ( test != "meany" ): - status.append( self.tests[ test ].__call__( statNode ) ) - + status.append( self.tests[ test ].__call__( statNode, pwarn, pfail ) ) + statusAttr = "OK" if ( "FAIL" in status ): statusAttr = "FAIL" elif ( "WARN" in status ): statusAttr = "WARN" - + self.node.setAttribute( "stest", statusAttr ) return statusAttr - + ## perform @f$\chi^2@f$ test # @param self "Me, myself and Irene" # @param statNode <stat> element - def __testChi2( self, statNode ): + def __testChi2( self, statNode, pwarn, pfail ): chi2 = ROOT.Double( 0.0 ) igood = ROOT.Long( 0 ) @@ -389,8 +446,8 @@ class DCubeTester( DCubeObject ): else: self.warn( ig ) - status = self.__getTestStatus( pval ) - self.sumTable["chi2"][status] = self.sumTable["chi2"][status] + 1 + status = self.__getTestStatus( pval, pwarn, pfail ) + self.sumTable["chi2"][status] = self.sumTable["chi2"][status] + 1 if ( ndf != 0 ): self.info( "*** Pearson's chi2 *** chi2 (/ndf) = %4.3f (/%d = %4.3f) status=%s" % ( chi2, @@ -407,7 +464,7 @@ class DCubeTester( DCubeObject ): pValueNode.setAttribute( "test", "chi2" ) pValueNode.setAttribute( "status", status ) - + counter = self.parent.getAttribute( "chi2" + status ) if ( not counter ): counter = "0" self.parent.setAttribute( "chi2" + status, "%d" % ( int(counter) + 1 ) ) @@ -422,7 +479,7 @@ class DCubeTester( DCubeObject ): ## perform Kolmogorov-Smirnoff test # @param self "Me, myself and Irene" # @param statNode <stat> element - def __testKS( self, statNode ): + def __testKS( self, statNode, pwarn, pfail ): nbBins,nbBinsSame,nbBinsDiff = self.__testEqual() self.debug("*** Kolmogorov-Smirnoff *** all none-empty bins=%d all equal non-empty bins=%d" % ( nbBins, nbBinsSame ) ) @@ -434,9 +491,9 @@ class DCubeTester( DCubeObject ): self.debug( "*** Kolmogorov-Smirnoff *** both histograms are equal!" ) else: pval = self.mon.KolmogorovTest( self.ref, "D" ) - - status = self.__getTestStatus( pval ) - self.sumTable["KS"][status] = self.sumTable["KS"][status] + 1 + + status = self.__getTestStatus( pval, pwarn, pfail ) + self.sumTable["KS"][status] = self.sumTable["KS"][status] + 1 self.info( "*** Kolmogorov-Smirnoff *** (D) p-value=%4.3f status=%s" % ( pval, status ) ) @@ -454,7 +511,7 @@ class DCubeTester( DCubeObject ): statNode.appendChild( pValueNode ) return status - + ## ** provide check if equal ** # returns (nbBins,nbBinsSame,nbBinsDiff) # nbBins - nb of bins not zero @@ -480,14 +537,14 @@ class DCubeTester( DCubeObject ): ## perform "bin-by-bin" statistic test # @param self "Me, myself and Irene" # @param statNode <stat> element - def __testBBB( self, statNode ): + def __testBBB( self, statNode, pwarn, pfail ): nbBins,nbBinsSame,nbBinsDiff = self.__testEqual() self.debug("*** bin-by-bin *** all none-empty bins=%d all equal non-empty bins=%d" % ( nbBins, nbBinsSame ) ) pval = 0.0 if ( nbBins != 0.0 ): - pval = nbBinsSame / nbBins + pval = nbBinsSame / nbBins self.debug("*** bin-by-bin *** p-value=%4.3f" % pval ) elif ( nbBinsSame == 0.0 ): pval = 1.0 @@ -497,11 +554,11 @@ class DCubeTester( DCubeObject ): # AS: this part is never called?! self.warn( "*** bin-by-bin *** reference histogram is empty, while monitored has some entries" ) self.debug( "*** bin-by-bin *** test failed" ) - - status = self.__getTestStatus( pval ) + + status = self.__getTestStatus( pval, pwarn, pfail ) self.info("*** bin-by-bin *** p-value=%4.3f status=%s" % ( pval, status ) ) - self.sumTable["bbb"][status] = self.sumTable["bbb"][status] + 1 + self.sumTable["bbb"][status] = self.sumTable["bbb"][status] + 1 pValueNode = self.xmldoc.createElement( "pvalue" ) pValueCData = self.xmldoc.createTextNode( "%4.3f" % pval ) @@ -529,13 +586,13 @@ class DCubeTester( DCubeObject ): avgEffref = self.ref.GetMean( 2 ) * 100 self.debug("*** MeanY Test *** refMean=%4.3f and monMean=%4.3f" % ( avgEffref, avgEffmon ) ) - + pval = abs(avgEffmon - avgEffref) status = self.__getMeanTestStatus( pval ) self.info("*** Mean Test *** p-value=%4.3f status=%s" % ( pval, status ) ) - self.sumTable["meanY"][status] = self.sumTable["meanY"][status] + 1 + self.sumTable["meanY"][status] = self.sumTable["meanY"][status] + 1 pValueNode = self.xmldoc.createElement( "pvalue" ) pValueCData = self.xmldoc.createTextNode( "%4.3f" % pval ) @@ -552,19 +609,19 @@ class DCubeTester( DCubeObject ): statNode.appendChild( pValueNode ) return status - - - ## get test status for given pvalue + + + ## get test status for given pvalue # @param self "Me, myself and Irene" # @param pval p-value from test - def __getTestStatus( self, pval ): - if ( ( pval < 0.0 or pval > 1.0 ) or - ( pval <= self.opts.pfail ) ): return "FAIL" - if ( pval > self.opts.pwarn ): return "OK" + def __getTestStatus( self, pval, pwarn, pfail ): + if ( ( pval < 0.0 or pval > 1.0 ) or + ( pval <= pfail ) ): return "FAIL" + if ( pval > pwarn ): return "OK" return "WARN" - ## get test status for given pvalue + ## get test status for given pvalue # @param self "Me, myself and Irene" # @param pval p-value from test def __getMeanTestStatus( self, pval ): @@ -580,10 +637,10 @@ class DCubeTester( DCubeObject ): plotOpts = self.node.getAttribute( "plotopts" ) status = self.__plotter.plot( self.node, self.mon, self.ref, plotOpts ) return status - + ## string representation of DCubeTester - # @param self "Me, myself and Irene" + # @param self "Me, myself and Irene" def __str__( self ): out = "*"*61 + "\n" out += "* RUN SUMMARY\n" @@ -591,7 +648,7 @@ class DCubeTester( DCubeObject ): out += "* objects processed = %d\n" % self.__nbObjs out += "* STATISTICS TESTS TABLE\n" out += "* " + "-"*45 + "\n" - out += "* | %-8s | %8s | %8s | %8s |\n" % ( "test", "OK", "WARN", "FAIL") + out += "* | %-8s | %8s | %8s | %8s |\n" % ( "test", "OK", "WARN", "FAIL") self.allGOOD = 0 self.allWARN = 0 self.allFAIL = 0 @@ -605,20 +662,20 @@ class DCubeTester( DCubeObject ): self.allFAIL += nbFAIL out += "* " + "-"*45+"\n" out += "* | %-8s | %8d | %8d | %8d |\n" % ( key, nbGOOD, nbWARN, nbFAIL ) - + out += "* " + "-"*45+"\n" - + out += "* | %-8s | %8d | %8d | %8d |\n" % ( "all", self.allGOOD, self.allWARN, self.allFAIL ) out += "* " + "-"*45+"\n" self.fracGOOD = 0.0 self.fracWARN = 0.0 self.fracFAIL = 0.0 - all = float( self.allGOOD + self.allWARN + self.allFAIL ) + all = float( self.allGOOD + self.allWARN + self.allFAIL ) if ( all ): - self.fracGOOD = 100 * float( self.allGOOD ) / all - self.fracWARN = 100 * float( self.allWARN ) / all + self.fracGOOD = 100 * float( self.allGOOD ) / all + self.fracWARN = 100 * float( self.allWARN ) / all self.fracFAIL = 100 * float( self.allFAIL ) / all out += "* | %% | %04.2f | %04.2f | %04.2f |\n" % ( self.fracGOOD, self.fracWARN, self.fracFAIL ) out += "* " + "-"*45+"\n" @@ -629,16 +686,16 @@ class DCubeTester( DCubeObject ): i = 1 for key, value in self.errors.iteritems( ): sev, what = key.split(";") - + out += "* [%02d] %4s %-30s - occured %d " % (i, sev, what, value ) if ( value == 1 ): out += "time\n" else: out += "times\n" i += 1 out += "*"*61+"\n" - + self.__status = "" - + if ( self.allFAIL != 0 ): self.__status = "FAIL" elif ( self.allWARN != 0 or self.nbErrors != 0 ): @@ -647,17 +704,17 @@ class DCubeTester( DCubeObject ): self.__status = "OK" out += "* OVERALL STATISTICS STATUS: %-4s\n" % self.__status - + out += "*"*61 - + return out - ## put summary to the logger and create summary node + ## put summary to the logger and create summary node # @param self "Me, myself and Irene" # @return summary XML Element def summary( self ): - - for line in str(self).split("\n"): + + for line in str(self).split("\n"): self.info( line ) summaryNode = self.xmldoc.createElement( "summary" ) @@ -667,18 +724,18 @@ class DCubeTester( DCubeObject ): testTable = self.xmldoc.createElement( "table" ) testTable.appendChild( self.__sumTableRow( [ "test", "OK", "WARN", "FAIL" ] ) ) - for test, results in self.sumTable.iteritems(): + for test, results in self.sumTable.iteritems(): testTable.appendChild( self.__sumTableRow( [ test, results["OK"], results["WARN"], results["FAIL"] ] ) ) - + testTable.appendChild( self.__sumTableRow( ["sum", self.allGOOD, self.allWARN, self.allFAIL ] ) ) testTable.appendChild( self.__sumTableRow( ["fraction", "%4.2f" % self.fracGOOD, "%4.2f" % self.fracWARN, "%4.2f" % self.fracFAIL ] ) ) - + summaryNode.appendChild( testTable ) errorsNode = self.xmldoc.createElement( "errors" ) @@ -690,12 +747,12 @@ class DCubeTester( DCubeObject ): errorNode.setAttribute( "times", "%d" % times ) errorNode.setAttribute( "what", error ) errorsNode.appendChild( errorNode ) - + summaryNode.appendChild( errorsNode ) - - return summaryNode - ## produce summary table row + return summaryNode + + ## produce summary table row # @param self "Me, myself and Irene" def __sumTableRow( self, what ): row = self.xmldoc.createElement( "tr" ) @@ -710,11 +767,18 @@ class DCubeTester( DCubeObject ): # @param self "Me, myself and Irene" def status( self ): return self.__status - - + + #check that values in histogram are not infinity or nan + def __checkValues( self, values ): + for val in values: + if ( math.isinf(abs( val ) ) or math.isnan( val ) ) : + return "BAD" + return "OK" + + ## # @class test_DCubeTester -# @author Krzysztof Daniel Ciba (Krzysztof.Ciba@NOSPAMgmail.com) +# @author Krzysztof Daniel Ciba (Krzysztof.Ciba@NOSPAMgmail.com) # @brief test case for DCubeTester class class test_DCubeTester( unittest.TestCase ): @@ -732,5 +796,5 @@ class test_DCubeTester( unittest.TestCase ): ## test case execution if __name__ == "__main__": pass - + diff --git a/Tools/DCubeClient/share/DCubeValid.xml b/Tools/DCubeClient/share/DCubeValid.xml index 55e421c88630..f2cb9d111eda 100644 --- a/Tools/DCubeClient/share/DCubeValid.xml +++ b/Tools/DCubeClient/share/DCubeValid.xml @@ -18,6 +18,7 @@ <branch>devval</branch> <branch>bugfix</branch> <branch>point1</branch> +<branch re="\d{2}\.\d{1}$">NN.N</branch> <branch re="\d{2}\.\d{1}\.\d{1}X$">NN.N.NX</branch> <branch re="\d{2}\.\d{1}\.\d{1}X\.Y$">NN.N.NX.Y</branch> <branch re="\d{2}\.\d{1}\.\d{1}X\.Y\-VAL$">NN.N.NX.Y-VAL</branch> @@ -44,14 +45,6 @@ <install>*</install> <!-- known CMTCONFIG values --> -<cmt>i686-slc3-gcc323-dbg</cmt> -<cmt>i686-slc3-gcc323-opt</cmt> -<cmt>i686-slc4-gcc34-dbg</cmt> -<cmt>i686-slc4-gcc34-opt</cmt> -<cmt>i686-slc4-gcc43-dbg</cmt> -<cmt>i686-slc4-gcc43-opt</cmt> -<cmt>x86_64-slc4-gcc34-dbg</cmt> -<cmt>x86_64-slc4-gcc34-opt</cmt> <cmt>i686-slc5-gcc34-dbg</cmt> <cmt>i686-slc5-gcc34-opt</cmt> <cmt>i686-slc5-gcc43-dbg</cmt> @@ -60,6 +53,16 @@ <cmt>x86_64-slc5-gcc34-opt</cmt> <cmt>x86_64-slc5-gcc43-dbg</cmt> <cmt>x86_64-slc5-gcc43-opt</cmt> +<cmt>x86_64-slc6-gcc46-opt</cmt> +<cmt>x86_64-slc6-gcc46-dbg</cmt> +<cmt>x86_64-slc6-gcc47-opt</cmt> +<cmt>x86_64-slc6-gcc47-dbg</cmt> +<cmt>x86_64-slc6-gcc48-opt</cmt> +<cmt>x86_64-slc6-gcc48-dbg</cmt> +<cmt>x86_64-slc6-gcc49-opt</cmt> +<cmt>x86_64-slc6-gcc49-dbg</cmt> +<cmt>x86_64-slc6-gcc62-opt</cmt> +<cmt>x86_64-slc6-gcc62-dbg</cmt> <!-- this one matches to ALL --> <cmt>*</cmt> -- GitLab