diff --git a/Trigger/TrigValidation/TrigValTools/CMakeLists.txt b/Trigger/TrigValidation/TrigValTools/CMakeLists.txt index f49eff884a76c1a30ddff94a14d819dbabc236da..45e23e0bfbd0c560ad5567cbfff911662776a93b 100644 --- a/Trigger/TrigValidation/TrigValTools/CMakeLists.txt +++ b/Trigger/TrigValidation/TrigValTools/CMakeLists.txt @@ -1,44 +1,36 @@ -################################################################################ -# Package: TrigValTools -################################################################################ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # Declare the package name: atlas_subdir( TrigValTools ) # External dependencies: -find_package( ROOT COMPONENTS Hist Graf Gpad RIO Core Tree MathCore pthread Graf3d Html Postscript Gui GX11TTF GX11 ) - -include_directories(src) +find_package( ROOT COMPONENTS Hist Graf Gpad RIO Core MathCore Postscript ) # Component(s) in the package: atlas_add_library( TrigValTools src/*.cxx PUBLIC_HEADERS TrigValTools - PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} - PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ) + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ) atlas_add_dictionary( TrigValToolsDict TrigValTools/TrigValToolsDict.h TrigValTools/selection.xml - INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} TrigValTools ) + LINK_LIBRARIES TrigValTools ) # Install files from the package: -atlas_install_python_modules( python/*.py python/TrigValSteering bin/chainDump.py ) +atlas_install_python_modules( python/*.py python/TrigValSteering bin/chainDump.py POST_BUILD_CMD ${ATLAS_FLAKE8} ) +atlas_install_scripts( bin/*.py test/*.py POST_BUILD_CMD ${ATLAS_FLAKE8} ) +atlas_install_scripts( bin/*.pl bin/*.sh ) atlas_install_data( share/*.json share/*.conf ) -atlas_install_runtime( bin/chainDump.py ) -atlas_install_scripts( bin/*.py bin/*.pl bin/*.sh test/*.py ) -atlas_install_generic( html/root2html/*.html - DESTINATION share/TrigValTools/root2html - EXECUTABLE ) # Unit tests: -atlas_add_test( TrigValSteering_flake8 - SCRIPT flake8 --select=ATL,F,E7,E9,W6 --enable-extension=ATL900,ATL901 ${CMAKE_CURRENT_SOURCE_DIR}/python/TrigValSteering - POST_EXEC_SCRIPT nopost.sh ) - atlas_add_test( TrigValSteering_unit_test SCRIPT test_unit_trigvalsteering.py PROPERTIES TIMEOUT 300 POST_EXEC_SCRIPT nopost.sh ) +atlas_add_test( rootcomp + SCRIPT test/test_rootcomp.sh ${CMAKE_CURRENT_SOURCE_DIR}/test/test_rootcomp.C + PROPERTIES TIMEOUT 120 + POST_EXEC_SCRIPT nopost.sh ) diff --git a/Trigger/TrigValidation/TrigValTools/TrigValTools/TRoot2Html.h b/Trigger/TrigValidation/TrigValTools/TrigValTools/TRoot2Html.h deleted file mode 100644 index 10c5dd2b9caacf7f7d4760d2f2a955dd55e6462a..0000000000000000000000000000000000000000 --- a/Trigger/TrigValidation/TrigValTools/TrigValTools/TRoot2Html.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration -*/ - -#ifndef TRIGVALTOOLS_TROOT2HTML_H -#define TRIGVALTOOLS_TROOT2HTML_H - -/** - * @file TRoot2Html.h - * @brief TRoot2Html class - * @author Frank Winklmeier - * - * $Id: TRoot2Html.h 702373 2015-10-22 13:55:56Z fwinkl $ - */ - -#include <fstream> -#include <vector> - -#include "TMultiFileLooper.h" -#include "TDirectory.h" -#include "TString.h" -#include "TH1.h" - -class TPRegexp; - -/** - * @class TRoot2Html - * @brief Create a (static) web page from ROOT histograms - * @author Frank Winklmeier - * - * Create images from histograms in root files and assemble them in - * a web page with a tree like naviation structure. - */ -class TRoot2Html : public TMultiFileLooper { - public: - - /// C'tor - TRoot2Html(); - /// D'tor - virtual ~TRoot2Html() {} - /// Copy C'tor (needed for Reflex dictionary generation) - TRoot2Html(const TRoot2Html& other); - - /// \name Processing hooks - //@{ - virtual void beginJob(); - virtual void endJob(); - virtual void beforeFile(); - virtual void afterFile(); - virtual void beforeDir(); - virtual void afterDir(); - virtual void processKey(TDirectory& dir, TKey& key); - //@} - - /// Output directory for HTML pages - void setOutputDir(const char* dir) {m_outDir = dir;} - - /// Set image size - void setImageSize(Int_t width, Int_t height) {m_imgWidth = width; m_imgHeight = height;} - - /// Add draw options for images (selected by regular expression on name) - void addDrawOptions(const char* regexp, const char* options); - - /// Add draw options for images (selected by regular expression on class name) - void addClassDrawOptions(const char* regexp, const char* options); - - /// Show full file name in tree - void showFullFileName(Bool_t show = kTRUE) {m_showFullFileName = show;} - - private: - TString m_fileList; - TString m_outDir; - Int_t m_imgHeight, m_imgWidth; - std::ofstream m_xml; - Int_t m_nodeId; - - Bool_t m_showFullFileName; - std::vector< std::pair<TPRegexp*,TString> > m_drawOptions; - std::vector< std::pair<TPRegexp*,TString> > m_classDrawOptions; - - TString hist2Png(TDirectory& dir, const TString& name); - TString getDrawOptions(const TH1& h); - - TString xmlTreeItem(const char* text); - TString xmlTreeItemClose(); - TString xmlUserData(const char* name, const char* data); - - // Not copyable due to the ofstream. - TRoot2Html& operator= (const TRoot2Html&); -}; - -#endif diff --git a/Trigger/TrigValidation/TrigValTools/TrigValTools/TrigValToolsDict.h b/Trigger/TrigValidation/TrigValTools/TrigValTools/TrigValToolsDict.h index 28064c1311102e7c58d25f36df8dce2660585121..f95c08a5c7e74a28d2da1c60e45d2da41f7c43e0 100644 --- a/Trigger/TrigValidation/TrigValTools/TrigValTools/TrigValToolsDict.h +++ b/Trigger/TrigValidation/TrigValTools/TrigValTools/TrigValToolsDict.h @@ -1,10 +1,9 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #include "TrigValTools/TRootCompare.h" #include "TrigValTools/TFileLooper.h" #include "TrigValTools/TMultiFileLooper.h" -#include "TrigValTools/TRoot2Html.h" #include "TPRegexp.h" diff --git a/Trigger/TrigValidation/TrigValTools/TrigValTools/selection.xml b/Trigger/TrigValidation/TrigValTools/TrigValTools/selection.xml index 512c99894514910c44d5c663988914aa57fce28b..2102ba54f93d5003f5d202303c9794f2e432e34f 100644 --- a/Trigger/TrigValidation/TrigValTools/TrigValTools/selection.xml +++ b/Trigger/TrigValidation/TrigValTools/TrigValTools/selection.xml @@ -2,5 +2,4 @@ <class name="TRootCompare" /> <class name="TFileLooper" /> <class name="TMultiFileLooper" /> - <class name="TRoot2Html" /> -</lcgdict> \ No newline at end of file +</lcgdict> diff --git a/Trigger/TrigValidation/TrigValTools/bin/COOLRates.py b/Trigger/TrigValidation/TrigValTools/bin/COOLRates.py index 1f1d37e5cc4678992b25099fdd4f62bd62794005..a5ec94e6668103e830bb98afe424c601b85b1ddd 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/COOLRates.py +++ b/Trigger/TrigValidation/TrigValTools/bin/COOLRates.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration #==================================================================================================================== @@ -13,8 +13,6 @@ __doc__ = "Fast Rate plotter from COOL database" from PyCool import cool from multiprocessing import Queue, cpu_count, Process from time import sleep -import random -import copy import argparse,sys,logging,time,os from math import log10 import signal @@ -45,7 +43,7 @@ if __name__=='__main__': parser.add_argument('-m','--processes',dest='PROCESSES',default=2,type=int,help='Sets number of processes for multiprocessing retrieval of COOL data') args = parser.parse_args() -from ROOT import gDirectory, TDatime, TProfile, TH1F, TCanvas, TLegend, TGaxis, gROOT, gStyle, SetOwnership, TColor, TLatex +from ROOT import TDatime, TProfile, TCanvas, TLegend, TGaxis, gROOT, SetOwnership, TColor, TLatex #==================================================================================================================== @@ -145,7 +143,7 @@ class COOLQueryWorker(): break resultBundle = self.processQuery(queryBundle) queueOut.put(resultBundle) - except Exception,exception: + except Exception as exception: logger.critical(exception) self.close() @@ -265,7 +263,7 @@ class QueryBundle(): self.IoVEnd = IoVEnd for request in payloadRequests: if not len(request)==3: - print payloadRequests + print(payloadRequests) sys.exit(0) self.payloadRequests = payloadRequests self.payloadRequirements = payloadRequirements @@ -315,7 +313,7 @@ def rateNameInfo(runLbRanges,mySignal,numProc=1): except Empty: sleep(.001) continue - if run == True: + if run is True: break runLbStart=run<<32 runLbEnd=runLbStart+1 @@ -400,7 +398,7 @@ def rateNameInfo(runLbRanges,mySignal,numProc=1): except Empty: time.sleep(.001) continue - if result == True: + if result is True: finished+=1 if finished==numProc: break continue @@ -561,7 +559,7 @@ def timeRangeToRunLbRange(timeRange): try: timeStart = time.strptime(timeStart,'%Y-%m-%d:%H:%M:%S') timeEnd = time.strptime(timeEnd,'%Y-%m-%d:%H:%M:%S') - except: + except Exception: logger.critical('Time range "{0}" does not match YYYY-MM-DD:HH:mm:ss;YYYY-MM-DD:HH:mm:ss'.format(timeRange)) sys.exit(0) @@ -600,7 +598,6 @@ def nanoTimeRangesToRunLbRanges(nanoTimeRanges): #==================================================================================================================== def fillNumberToRunLbRange(fillNumbers): - runLbRanges = [] minFill = min(fillNumbers)-1 worker = COOLQueryWorker() result = {} diff --git a/Trigger/TrigValidation/TrigValTools/bin/check_log.py b/Trigger/TrigValidation/TrigValTools/bin/check_log.py index 9c4271afa98dc28bf0587aa95b2dde0d2b2af467..75e21bf84d8bbbe2ced1d34782396805173a55e5 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/check_log.py +++ b/Trigger/TrigValidation/TrigValTools/bin/check_log.py @@ -15,24 +15,24 @@ If no config file is provided, all errors will be shown.' # Error keywords errorRegex = [ - '^ERROR ', ' ERROR ', ' FATAL ', 'CRITICAL ', 'ABORT_CHAIN', - '^Exception\:', - '^Caught signal', - '^Core dump', - 'inconsistent use of tabs and spaces in indentation', - 'glibc detected', - 'tcmalloc\: allocation failed', - 'athenaHLT.py\: error', - 'HLTMPPU.*Child Issue', - 'HLTMPPU.*Configuration Issue', - 'There was a crash', - 'illegal instruction', - 'failure loading library', - 'Cannot allocate memory', - 'in state: CONTROLREADY$', - '^\s*missing data: ', - '^\s*can be produced by alg(s): ', - 'pure virtual method called' + r'^ERROR ', ' ERROR ', ' FATAL ', 'CRITICAL ', 'ABORT_CHAIN', + r'^Exception\:', + r'^Caught signal', + r'^Core dump', + r'inconsistent use of tabs and spaces in indentation', + r'glibc detected', + r'tcmalloc\: allocation failed', + r'athenaHLT.py\: error', + r'HLTMPPU.*Child Issue', + r'HLTMPPU.*Configuration Issue', + r'There was a crash', + r'illegal instruction', + r'failure loading library', + r'Cannot allocate memory', + r'in state: CONTROLREADY$', + r'^\s*missing data: ', + r'^\s*can be produced by alg(s): ', + r'pure virtual method called' ] # Add list of all builtin Python errors @@ -42,11 +42,11 @@ errorRegex.extend(builtinErrors) # Traceback keywords traceback = [ - 'Traceback', - 'Shortened traceback', - 'stack trace', - '^Algorithm stack', - '^#\d+\s*0x\w+ in ' + r'Traceback', + r'Shortened traceback', + r'stack trace', + r'^Algorithm stack', + r'^#\d+\s*0x\w+ in ' ] errorRegex.extend(traceback) @@ -113,7 +113,7 @@ def parseConfig(): line = line[1:-1] ignorePattern.append(line) noConfig = False - except: + except Exception: print('No config file, all warnings/errors will be printed') noConfig = True @@ -124,9 +124,9 @@ def scanLogfile(): tPattern = re.compile('|'.join(traceback)) global msgLevels global logFileAddress - if args.warnings == True: + if args.warnings is True: pattern = warningRegex - if args.errors == True: + if args.errors is True: pattern = errorRegex msgLevels = re.compile('|'.join(pattern)) igLevels = re.compile('|'.join(ignorePattern)) @@ -136,7 +136,7 @@ def scanLogfile(): tracing = False for line in logFile: #Tracing only makes sense for errors - if args.errors == True and re.search(tPattern,line): + if args.errors is True and re.search(tPattern,line): tracing = True elif line =='\n': tracing = False diff --git a/Trigger/TrigValidation/TrigValTools/bin/histSizes.py b/Trigger/TrigValidation/TrigValTools/bin/histSizes.py index 4ea3c2d3d37fa9c8d83adc8886b21f857c10828f..10d30e3bd526ec1106f74948beb427da70d68eed 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/histSizes.py +++ b/Trigger/TrigValidation/TrigValTools/bin/histSizes.py @@ -13,11 +13,11 @@ def filledBins(h): return sum([1 for i in range(N) if h.At(i)!=0]) def hasLabels(h): - return (h.GetXaxis().GetLabels()!=None) + return (h.GetXaxis().GetLabels() is not None) def missingLabels(h): l = h.GetXaxis().GetLabels() - return (l!=None and h.GetXaxis().GetNbins()!=l.GetSize()) + return (l is not None and h.GetXaxis().GetNbins()!=l.GetSize()) def addDirList(dir,path,hists): list=dir.GetListOfKeys() @@ -29,9 +29,9 @@ def addDirList(dir,path,hists): else: h = key.ReadObj() if not h.InheritsFrom('TH1'): continue - if opts.labeled==True and not hasLabels(h): continue - if opts.misslabel==True and not missingLabels(h): continue - if opts.empty==True and h.GetEntries()>0: continue + if opts.labeled is True and not hasLabels(h): continue + if opts.misslabel is True and not missingLabels(h): continue + if opts.empty is True and h.GetEntries()>0: continue b = filledBins(h) if opts.filled else h.GetSize() hists[path+name]=(cname,b) @@ -58,8 +58,7 @@ def byName(hists, nameFunc): return algs def byAlg(hists): - f = lambda h : h.split('/',2)[1] - return byName(hists, f) + return byName(hists, lambda h : h.split('/',2)[1]) def main(): @@ -108,11 +107,11 @@ def main(): if not opts.byAlg: opts.byName = True - if opts.byName==True: + if opts.byName is True: for h,v in sorted(hists.items(), key=sortKey): print('%-80s %10s %10s' % (h,v[0],v[1])) - if opts.byAlg==True: + if opts.byAlg is True: algs = byAlg(hists) for h,v in sorted(algs.items(), key=sortKey): print('%-80s %10s %10s' % (h,v[0],v[1])) diff --git a/Trigger/TrigValidation/TrigValTools/bin/regtest.py b/Trigger/TrigValidation/TrigValTools/bin/regtest.py index e13ea5aceca581ed7e2bd6c9f9c001a916a48703..84d6aa0d859f4391daf49b617d15a23a67c3b32b 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/regtest.py +++ b/Trigger/TrigValidation/TrigValTools/bin/regtest.py @@ -1,6 +1,8 @@ #!/usr/bin/env python -# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +from __future__ import print_function import re import argparse @@ -18,7 +20,7 @@ def progErrorExit(message, exitcode): failkey except NameError: failkey = 'FAILURE' - print 'regtest.py:', failkey, message + print('regtest.py: %s %s' % (failkey, message)) sys.exit(exitcode) def commandLine(): @@ -66,12 +68,12 @@ def commandLine(): ) global args args = parser.parse_args() - if help == True: + if help is True: usage() progErrorExit('usage', -1) def usage(): - print''' + print(''' Usage: regtest.py [options] Testing tool for comparing marked lines in a log file against a reference @@ -95,7 +97,7 @@ def usage(): Technical info: Lines which match the regular expression - ''' + ''') def regtest(): with open(args.inputfile,'r') as inpfile: @@ -105,29 +107,29 @@ def regtest(): matchline += 1 if matchline == 0: - print '=== Alert!', failkey, 'no lines matching', linematch, 'in LOG' + print('=== Alert!', failkey, 'no lines matching', linematch, 'in LOG') result = True exit() - if debug == True: - print 'regtest.py,: debug: diff -b', args.inputfile, args.reffile + if debug is True: + print('regtest.py,: debug: diff -b', args.inputfile, args.reffile) command = 'diff -b ' + args.inputfile + ' ' + args.reffile rc = os.system(command) - if rc == False: - print '=== Output is the same as reference.' + if rc is False: + print('=== Output is the same as reference.') # result = False result = 0 else: - print '''=== Alert!''', failkey, '''input file (<) differs from reference (>) - If this change is understood, to update the reference file please type: - cp ''', args.inputfile, args.reffile -# result = True + print('''=== Alert!''', failkey, '''input file (<) differs from reference (>) + If this change is understood, to update the reference file please type: + cp ''', args.inputfile, args.reffile) + # result = True result = 1 - if debug == True: - print 'regtest.py debug: returning result', result + if debug is True: + print('regtest.py debug: returning result', result) return result if __name__ == '__main__': diff --git a/Trigger/TrigValidation/TrigValTools/bin/root2html.py b/Trigger/TrigValidation/TrigValTools/bin/root2html.py index 2e7fbaeeb7833515866861b8f51bcd68aaf20ccb..0fbd03e0d8c0ecaed5f6aff27f862d43af3b90a7 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/root2html.py +++ b/Trigger/TrigValidation/TrigValTools/bin/root2html.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # @file: root2html.py # @purpose: Generate the index.htm for a list of root files # @author: Will Buttinger @@ -27,8 +27,6 @@ html_template = """ import sys -import os -from AthenaCommon.Utils.unixtools import FindFile def main(): @@ -48,7 +46,7 @@ def main(): o_html.writelines(html_template%d) o_html.flush() o_html.close() - print "Wrote index.htm file" + print("Wrote index.htm file") return 0 diff --git a/Trigger/TrigValidation/TrigValTools/bin/rootcomp.py b/Trigger/TrigValidation/TrigValTools/bin/rootcomp.py index 56e0221bfa870f1df7fac36a47300560ef563be4..a2a5a081c90e51e6dc5f546f27d43bb8dd87f51e 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/rootcomp.py +++ b/Trigger/TrigValidation/TrigValTools/bin/rootcomp.py @@ -9,44 +9,6 @@ from __future__ import print_function import sys import os import os.path -from TrigValTools.TrigRootUtils import lsroot - - -def diffFiles(ref,file,opts): - """Compare the keys in both files""" - - import ROOT - tref = ROOT.TFile(ref) - tfile = ROOT.TFile(file) - if tref.IsZombie() or tfile.IsZombie(): return - - lsref = lsroot(tref.GetDirectory(opts.refBaseDir)) - lsfile = lsroot(tfile.GetDirectory(opts.fileBaseDir)) - tref.Close() - tfile.Close() - del tref - del tfile - - diff = list(set(lsref).difference(set(lsfile))) - - import re - selection = lambda x: True - - # Only show diffs that are not on the skip list ... - if len(opts.skip)>0: - selection = lambda x : not reduce(lambda a,b:a|b,[re.search(pat,x)!=None for pat in opts.skip]) - # ... or pass the selection - elif len(opts.select)>0: - selection = lambda x : reduce(lambda a,b:a|b,[re.search(pat,x)!=None for pat in opts.select]) - - refonly = filter(selection,filter(lambda s:s[0]=='-',diff)) - - if len(refonly)>0: - print("\nHistograms only found in reference:") - for s in refonly: print(s) - - return - def main(): @@ -184,12 +146,12 @@ def main(): # Now import ROOT - import cppyy + import cppyy # noqa: F401 try: from PerfMonAna import PyRootLib ROOT = PyRootLib.importRoot( batch=True ) except ImportError: - import ROOT + import ROOT # noqa: F401 sys.stdout.flush() sys.stderr.flush() @@ -247,9 +209,6 @@ def main(): print("GZipping postscript file -> %s.ps.gz" % opts.outFile) os.system("gzip -f %s.ps" % (opts.outFile)) - # List histograms that are only found in reference - #diffFiles(args[0],args[1],opts) # this is quite slow, disable it - if rc != 0: result = 255 elif valid.totalHist()>0: diff --git a/Trigger/TrigValidation/TrigValTools/bin/trigDumpTimers.py b/Trigger/TrigValidation/TrigValTools/bin/trigDumpTimers.py index 7affe68bfe7641e1ad007c3550515ec793bd7ccb..6f1ba6fee5f22446fe6e7fe9e56322b05a9144bb 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/trigDumpTimers.py +++ b/Trigger/TrigValidation/TrigValTools/bin/trigDumpTimers.py @@ -1,14 +1,12 @@ #!/usr/bin/env python -# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -# @file: dumpTimes.py +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# @file: trigDumpTimers.py # @purpose: Script to dump the timing histograms from expert-monitoring.root/TIMERS # @author: Stewart Martin-Haugh -import argparse import ROOT from optparse import OptionParser -import os import re from TrigValTools.TrigRootUtils import lsroot @@ -31,7 +29,7 @@ def get_matches(pattern, exclude, myFile): if exclude: regex_exclude = re.compile(".*" + exclude + ".*") for name in names: - if not "TIME" in name: + if "TIME" not in name: continue if not regex.match(name): continue @@ -44,18 +42,18 @@ def get_matches(pattern, exclude, myFile): def main(): parser = OptionParser() parser.add_option("-p", "--pattern", dest="pattern", type = "string", default = None, - help="Pattern to match histogram to") + help="Pattern to match histogram to") parser.add_option("-x", "--exclude", dest="exclude", type = "string", default = None, - help="Pattern to exclude histogram from matching") + help="Pattern to exclude histogram from matching") (options, args) = parser.parse_args() - print(options, args) + for arg in args: print(arg) myFile = ROOT.TFile(arg) pattern = ".*" if (options.pattern): pattern = options.pattern - get_matches(options.pattern, options.exclude, myFile) + get_matches(pattern, options.exclude, myFile) if __name__ == "__main__": diff --git a/Trigger/TrigValidation/TrigValTools/bin/trigslimval.py b/Trigger/TrigValidation/TrigValTools/bin/trigslimval.py deleted file mode 100755 index a022377a035dcdd5f9fe9a4788f6b26d888aa7e8..0000000000000000000000000000000000000000 --- a/Trigger/TrigValidation/TrigValTools/bin/trigslimval.py +++ /dev/null @@ -1,540 +0,0 @@ -#!/usr/bin/env python - -# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration -# -# @file TrigSlimVal.py -# @brief Checks the output of TrigSlimValidation run logs -# @author Ben Smith <bcsmith@fas.harvard.edu> - -import os -import sys -from sets import Set - -# Global variables -variables = Set() -failures = list() -testsRun = 0 - -# variable class -class Variable: - name = "" - string = "" - - def __init__(self, name, string): - self.name = name - self.string = string - def __repr__(self): - return 'Variable \'' + self.name + '\' from string \'' + self.string + '\'' - -# comparison class -class Comparison: - name = "Comparison" - string = "" - - def __init__(self, name, string): - self.name = name - self.string = string - def __repr__(self): - return 'Comparison \'' + self.name + '\' with definition \'' + self.string + '\'' - - def passes(self, test, event): - # replace words with variable values - words = self.string.split(' ') - comparison = '=' - currside = 0 - leftVal = 0 - rightVal = 0 - operation = '+' - allVals = list() - for word in words: - # check if its an operation - if len(word) == 1 and not word.isdigit(): - if word == '+': - operation = '+' - allVals.append('+') - elif word == '-': - operation = '-' - allVals.append('-') - elif word == '=': - operation = '+' - comparison = '=' - allVals.append('=') - currside = 1 - elif word == '<': - operation = '+' - comparison = '<' - allVals.append('<') - currside = 1 - elif word == '>': - operation = '+' - comparison = '>' - allVals.append('>') - currside = 1 - else: - return 'Error: cannot parse word ' + word + ' from comparison ' + self.string - continue - # replace the word with variable value - val = '' - if word.startswith('BASE.'): - val = test.getBaseVal(word.replace('BASE.', ''), event) - elif word.startswith('MOD.'): - val = test.getModifiedVal(word.replace('MOD.', ''), event) - elif word.isdigit(): - val = int(word) - if isinstance(val, basestring) and val.count('not defined in') > 0: - val = 0 - if not isinstance(val, int): - return 'ERROR: Cannot parse word ' + word + ' from comparison ' + self.string - - allVals.append('%d' % val) - if operation == '-': - val = val * -1 - if currside == 0: - leftVal += val - else: - rightVal += val - - if leftVal == 0 and rightVal == 0: - return 'PASSED' - if comparison == '=' and leftVal == rightVal: - return 'PASSED' - if comparison == '<' and leftVal < rightVal: - return 'PASSED' - if comparison == '>' and leftVal > rightVal: - return 'PASSED' - - message = 'FAILED comparison \'' + self.name +'\': ' + self.string - message += ' ( ' - for x in allVals: - message += x + ' ' - message += ')' - message += ' Event: %d' % event - return message - -# test class -class Test: - name = "TestClass" - alterableVariables = Set() - comparisons = Set() - baseValDictArray = list() - modifiedValDictArray = list() - - def __init__(self, name): - self.name = name - def __repr__(self): - str = 'Test ' + self.name - str += '\n\tAlterableVariables: ' + self.alterableVariables.__repr__() - str += '\n\tComparisons: ' + self.comparisons.__repr__() - str += '\n\tBase value dictionary array: ' + self.baseValDictArray.__repr__() - str += '\n\tModified value dictionary array: ' + self.modifiedValDictArray.__repr__() - return str - - def getBaseVal(self, name, event): - if not len(self.baseValDictArray) > event: - return 'No entries in the base value dictionary for event %d' % event - baseValDict = self.baseValDictArray[event]; - v = getVariable(name) - if not isinstance(v, Variable): - return v - if not v in baseValDict: - return 'Variable ' + name + ' not defined in the base value dictionary' - return baseValDict[v] - - def getModifiedVal(self, name, event): - if not len(self.modifiedValDictArray) > event: - return 'No entries in the modified value dictionary for event %d' % event - modifiedValDict = self.modifiedValDictArray[event]; - v = getVariable(name) - if not isinstance(v, Variable): - return v - if not v in modifiedValDict: - return 'Variable ' + name + ' not defined in the modified value dictionary' - return modifiedValDict[v] - - def runTests(self): - global testsRun - global failures - - testsRun = testsRun + 1 - # loop through events and check each one - if not len(self.baseValDictArray) == len(self.modifiedValDictArray): - return 'Initialization error: base and modified value dictionary arrays have different sizes' - i = 0 - for i in range(0, len(self.baseValDictArray)): - # check that the non-alterable variables have not changed - for v in variables.difference(map(getVariable, self.alterableVariables)): - if isinstance(self.getBaseVal(v.name, i),basestring): - continue - c = Comparison('UnalterableVariable: ' + v.name, 'BASE.' + v.name + ' = ' + 'MOD.' + v.name) - val = c.passes(self, i) - if not val == 'PASSED': - failures.append(self.name + ': ' + val) - return val - # check that the comparisons pass - for c in self.comparisons: - val = c.passes(self, i) - if not val == 'PASSED': - failures.append(self.name + ': ' + val) - return val - # if we made it this far, then we passed! - return 'PASSED' - -# variable functions -def getVariable(name): - for v in variables: - if v.name == name: - return v - return 'Variable ' + name + ' not found' - -def addVariable(name, string): - if isinstance(getVariable(name), Variable): - return 'Could not add variable ' + name + '... Variable already exists' - v = Variable(name, string) - variables.add(v) - return v - -# parsing functions -def matchLine(line, valDict): - # ignore blank lines - if len(line) == 0: - return '' - # check if any of the variable strings appear in the line - for v in variables: - if line.count(v.string) > 0: - if v in valDict: - return 'Wanted to assign line ' + line + ' to var ' + v.name + ' but ' + v.name + ' is already assigned!' - # split the line by the colon - words = line.split(':') - if not len(words) == 2: - message = 'Wanted to assign line ' + line + ' to var ' + v.name - message = message + ' but line has wrong num (' + words.length() + ') of words' - return messsage - val = int(words[1].replace(' ', '').replace('\n', '')) - valDict[v] = val - return '' - return 'Unable to match line ' + line - -def parseEvent(log, valDict): - for line in log: - errorVal = matchLine(line, valDict) - if not errorVal == '': - return errorVal - return '' - -def parseLog(logFile, valDictArray): - if not os.path.exists(logFile): - return 'File ' + logFile + ' does not exist' - file = open(logFile, 'r') - - # split the log file by event by looking for the lines - startBlock = 'START of TrigSlimValidation DUMP' - endBlock = 'END of TrigSlimValidation DUMP' - log = list() - inBlock = False - eventNum = 1 - - for line in file.readlines(): - # if we see a start block, prepare to read an event - if line.count(startBlock) > 0: - if inBlock: - return 'Wanted to start event %d, but event %d never closed' % (eventNum, eventNum - 1) - inBlock = True - log[:] = [] - continue - if line.count(endBlock) > 0: - # if we see an end block, close event and parse it - if not inBlock: - return 'Wanted to end event %d, but event was never opened!' % (eventNum) - valDict = dict() - errorVal = parseEvent(log, valDict) - valDictArray.append(valDict) - if not errorVal == '': - return errorVal - inBlock = False - eventNum = eventNum + 1 - continue - # if we're in an event block, add the log line - # otherwise, just ignore the line - if inBlock: - log.append(line) - file.close() - - return '' - -def setupTest(test, baseLog, modifiedLog): - test.baseValDictArray = list() - errorVal = parseLog(baseLog, test.baseValDictArray) - if not errorVal == '': - print '\nParsing the base log ' + baseLog + ' for test', - print test.name + ' failed with the following error:' - print errorVal - print 'This is unrecoverable... exiting!\n' - exit() - test.modifiedValDictArray = list() - errorVal = parseLog(modifiedLog, test.modifiedValDictArray) - if not errorVal == '': - print '\nParsing the modified log ' + modifiedLog + ' for test', - print test.name + ' failed with the following error:' - print errorVal - print 'This is unrecoverable... exiting!\n' - exit() - - -############## TrigSlimValidation specific code ################# -def buildObjectList(log, key): - s = Set() - - if not os.path.exists(log): - return 'File ' + log + ' does not exist' - file = open(log, 'r') - for line in file.readlines(): - if line.count(key) > 0: - for word in line.split(' '): - if word.count(':') > 0: - s.add(word.replace(':', '')) - break - return s - -def buildStreamRemovedTest(stream, baseLog, modLog, features): - RSTest = Test('RS' + stream) - setupTest(RSTest, baseLog, modLog) - RSTest.alterableVariables = Set(['elements', 'intermediates', 'stream'+stream, 'links', 'features', 'featureless', 'ghosts', 'seeds', 'seededBy', 'sameRoI','longest', 'unassociated']) - RSTest.alterableVariables.add('unassociatedgroup') - # All features can change, as entire streams are removed - for f in features: - RSTest.alterableVariables.add('feature'+f) - RSTest.comparisons = Set([Comparison('StreamRemoved', 'MOD.stream' + stream + ' < BASE.stream' + stream)]) - return RSTest - -def buildFeatureRemovedTest(feature, baseLog, modLog): - RFTest = Test('RF'+feature) - setupTest(RFTest, baseLog, modLog) - RFTest.alterableVariables = Set(['features','featureless','links','feature'+feature]) - RFTest.comparisons = Set([Comparison('DistinctFeatures', 'BASE.features = MOD.features + 1'), - Comparison('FeatureLinks', 'BASE.links < 1 + MOD.links + BASE.feature'+feature), - Comparison('FeatureRemoved', 'MOD.feature'+feature+' = 0')]) - return RFTest - -def buildSqueezeTest(baseLog, modLog, streams, features): - SqueezeTest = Test('Squeeze') - setupTest(SqueezeTest, baseLog, modLog) - SqueezeTest.alterableVariables = Set(['intermediates', 'seeds', 'seededBy', 'sameRoI', 'elements', 'unassociated', 'longest', 'shortest', 'links','unassociatedgroup']) - for s in streams: - SqueezeTest.alterableVariables.add('stream'+s) - SqueezeTest.comparisons = Set([Comparison('IntermeidateElements','MOD.intermediates = 0'), - Comparison('Elements', 'MOD.elements + BASE.intermediates = BASE.elements'), - Comparison('LongestChain', 'MOD.longest = 3'), - Comparison('ShortestChain', 'MOD.shortest < 4')]) - # When you squeeze, you can actually increase the number of occurrences of a given feature - # if you remove a node with multiple children. Thus, we need to check that the number - # of occurrences of each feature is the same or larger - for f in features: - SqueezeTest.alterableVariables.add('feature'+f) - SqueezeTest.comparisons.add(Comparison('FeatureIncrease'+f, 'MOD.feature'+f+' + 1 > BASE.feature' + f)) - return SqueezeTest - -def buildNoSlimTest(baseLog, modLog): - # No Slim Test - # Nothing changes, so this is super easy! - NoSlimTest = Test("NoSlimTest") - setupTest(NoSlimTest, baseLog, m) - return NoSlimTest - -def buildCombinedTest(test1, test2): - test = Test(test1.name + test2.name) - test.alterableVariables = test1.alterableVariables.union(test2.alterableVariables) - test.comparisons = test1.comparisons.union(test2.comparisons) - test.baseValDictArray = test1.baseValDictArray - test.modifiedValDictArray = test1.modifiedValDictArray - # There are some special rules for combining RF and squeeze tests - # Basically, squeeze tests require that the number of occurrences of a feature - # stays the same or increases. We need to remove this required when we combine - # with an RF test, but only for the feature that was removed - toRemove = Set() - if test1.name.count('RF') > 0: - feature = test1.name.replace('RF', '') - for c in test.comparisons: - if c.name.startswith('FeatureIncrease') and c.name.count(feature) > 0: - toRemove.add(c) - if test2.name.count('RF') > 0: - feature = test2.name.replace('RF', '') - for c in test.comparisons: - if c.name.startswith('FeatureIncrease') and c.name.count(feature) > 0: - toRemove.add(c) - test.comparisons = test.comparisons.difference(toRemove) - return test - -# Begin main - -def main(): - - # read command line options - from optparse import OptionParser - parser = OptionParser(usage = "usage: %prog [options]", - description = "Compares output of TrigSlimValAlg on slimmed and unslimmed AODs to validate TrigNavigationSlimming.") - parser.add_option("-b", "--base", action = "store", dest = "baseLog", default = "TrigSlimValidation_Base.log", help = "Base log file") - parser.add_option("-m", "--modified", action = "append", dest = "modifiedLog", default = list(), help = "Modified log file") - parser.add_option("-t", "--test", action = "append", dest = "testType", default = list(), help = "Test to run") - parser.add_option("-f", "--feature", action = "append", dest = "removedFeature", default = list(), help = "Removed feature (if needed by test)") - parser.add_option("-s", "--stream", action = "append", dest = "removedStream", default = list(), help = "Removed stream (if needed by test)") - - (opts, args) = parser.parse_args() - - if len(args) > 0: - print - print 'Unable to parse option: ' + args[0] - print 'This is unrecoverable... exiting!\n' - print - exit() - - # Populate all variables - baseLog = opts.baseLog - modifiedLogs = opts.modifiedLog - testTypes = opts.testType - removedFeatures = opts.removedFeature - removedStreams = opts.removedStream - if len(modifiedLogs) == 0 and len(testTypes) == 0: - print - print 'You must specify either a modified log (with -m) or a test type (with -t)' - print - exit() - if len(modifiedLogs) == 0: - for t in testTypes: - modifiedLog = 'TrigSlimValidation_' + t + '.log' - print - print 'Assuming modified log file at ' + modifiedLog + ' based upon test type ' + t - print - modifiedLogs.append(modifiedLog) - if len(testTypes) == 0: - for l in modifiedLogs: - frontRemoved = l.split('_') - if not len(frontRemoved) == 2: - print - print 'Unable to determine implicit test type from modified log', - print l + '... you should supply it explicity with -t' - print - exit() - backRemoved = frontRemoved[1].split('.') - if not len(backRemoved) == 2: - print - print 'Unable to determine implicit test type from modified log', - print l + '... you should supply it explicity with -t' - print - exit() - t = backRemoved[0] - print - print 'Assuming test type ' + t + ' based upon modified log file ' + l - print - testTypes.append(t) - - # Build feature, stream, and group lists - features = buildObjectList(baseLog, 'Occurrences of feature') - if not isinstance(features, Set): - print - print 'Unable to build feature list due to the following error:' - print features - print 'This is unrecoverable... exiting!\n' - exit() - streams = buildObjectList(baseLog, 'Elements associated with stream') - if not isinstance(streams, Set): - print - print 'Unable to build stream list due to the following error:' - print streams - print 'This is unrecoverable... exiting!\n' - exit() - groups = buildObjectList(baseLog, 'Elements associated with group') - if not isinstance(groups, Set): - print - print 'Unable to build group list due to the following error:' - print groups - print 'This is unrecoverable... exiting!\n' - exit() - - # Define needed variables - addVariable('elements', 'Number of trigger elements:') - addVariable('features', 'Number of distinct features:') - addVariable('intermediates', 'Number of intermediate trigger elements:') - addVariable('featureless', 'Number of featureless trigger elements:') - addVariable('ghosts', 'Number of ghost trigger elements:') - addVariable('RoIs', 'Number of RoIs:') - addVariable('longest', 'Longest chain:') - addVariable('shortest', 'Shortest chain:') - addVariable('links', 'Number of feature links:') - addVariable('seeds', 'Number of seeds relations:') - addVariable('seededBy', 'Number of seeded by relations:') - addVariable('sameRoI', 'Number of same RoI relations:') - - # add feature, stream, and group variables - for f in features: - addVariable('feature'+f, 'Occurrences of feature ' + f + ':') - for s in streams: - addVariable('stream'+s, 'Elements associated with stream ' + s + ':') - for g in groups: - addVariable('group'+g, 'Elements associated with group ' + g + ':') - addVariable('unassociated', 'Elements unassociated with any stream:') - addVariable('unassociatedgroup', 'Elements unassociated with any group:') - - # Define some useful tests - AllTests = list() - - for t,m in zip(testTypes,modifiedLogs): - if t == 'NoSlim': - AllTests.append(buildNoSlimTest(baseLog, m)) - if t == 'RF': - if len(removedFeatures) == 0: - print - print "Could not find feature to remove for test " + t + ' with modified log file ' + m - print - exit() - AllTests.append(buildFeatureRemovedTest(removedFeatures.pop(0), baseLog, m)) - if t == 'RS': - if len(removedStreams) == 0: - print - print "Could not find stream to remove for test " + t + ' with modified log file ' + m - print - exit() - AllTests.append(buildStreamRemovedTest(removedStreams.pop(0), baseLog, m, features)) - if t == 'Squeeze': - AllTests.append(buildSqueezeTest(baseLog, m, streams, features)) - if t == 'SqueezeRF': - if len(removedFeatures) == 0: - print - print "Could not find feature to remove for test " + t + ' with modified log file ' + m - print - exit() - SqueezeTest = buildSqueezeTest(baseLog, m, streams, features) - RFTest = buildFeatureRemovedTest(removedFeatures.pop(0), baseLog, m) - AllTests.append(buildCombinedTest(SqueezeTest, RFTest)) - - # Check the tests - print - print 'Running tests...' - print - - for t in AllTests: - print t.name + ': ' + t.runTests() - - print - print 'Tests complete!' - print - - # Print the final report - print - print 'Final report:' - print 'Tests passed: %d/%d' % (testsRun - len(failures), testsRun) - print 'Tests failed: %d/%d' % (len(failures), testsRun) - print - - if len(failures) > 0: - print - print "trigslimval.py ERROR: Failures found" - print - print 'Failures:' - for f in failures: - print f - print - print - -if __name__ == "__main__": - sys.exit(main()) - diff --git a/Trigger/TrigValidation/TrigValTools/html/root2html/index.html b/Trigger/TrigValidation/TrigValTools/html/root2html/index.html deleted file mode 100644 index faa2a8df09bd598e5283efb9338d3a7af250e975..0000000000000000000000000000000000000000 --- a/Trigger/TrigValidation/TrigValTools/html/root2html/index.html +++ /dev/null @@ -1,12 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<!-- Main html file for root2html --!> - -<html> - <head> - <title>HLT monitoring histograms</title> - </head> - <frameset cols="320,*" border="0"> - <frame src="tree.html" name="tree"></frame> - <frame src="" name="img"></frame> - </frameset> -</html> diff --git a/Trigger/TrigValidation/TrigValTools/html/root2html/tree.html b/Trigger/TrigValidation/TrigValTools/html/root2html/tree.html deleted file mode 100644 index fc7a2ea9109347529edb1f890a399db05793e115..0000000000000000000000000000000000000000 --- a/Trigger/TrigValidation/TrigValTools/html/root2html/tree.html +++ /dev/null @@ -1,63 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> -<!-- Tree navigation for root2html --> - -<html> - <body> - <link rel="STYLESHEET" type="text/css" href="http://atlas-project-trigger-release-validation.web.cern.ch/atlas-project-trigger-release-validation/www/dhtmlxTree/css/dhtmlXTree.css"> - <script src="http://atlas-project-trigger-release-validation.web.cern.ch/atlas-project-trigger-release-validation/www/dhtmlxTree/js/dhtmlXCommon.js"></script> - <script src="http://atlas-project-trigger-release-validation.web.cern.ch/atlas-project-trigger-release-validation/www/dhtmlxTree/js/dhtmlXTree.js"></script> - - <input type="button" name="draw" value="Show selected" onClick="drawSelected()"></input> - <input type="button" name="clear" value="ClearAll" onClick="clearAll()"></input> - <p><font size="-2"> - To show histograms, click on single leaf or select multiple and click on "Show selected". - (Please be patient while the tree loads...) - </font></p> - <div id="naviTree" style="width:300"></div> - <div id="footer"><font size="-2">Created by root2html<br>(C) Frank Winklmeier<br>powered by <a href="http://www.scbr.com/docs/products/dhtmlxTree/" target="new">dhtmlXTree</a></font></div> - <script language="JavaScript"> - tree = new dhtmlXTreeObject('naviTree',"100%","80%",0); - tree.setImagePath("http://atlas-project-trigger-release-validation.web.cern.ch/atlas-project-trigger-release-validation/www/dhtmlxTree/imgs/"); - tree.enableCheckBoxes(true); - tree.enableThreeStateCheckboxes(true); - tree.loadXML("tree.xml"); - tree.setOnClickHandler(doOnClick); - - // onClick event handler - // Load image path on click - function doOnClick(nodeId) { - var imgPath = tree.getUserData(nodeId,"img"); - if (imgPath != undefined) parent["img"].location.href = imgPath; - } - - // show all selected plots - function drawSelected() { - var doc = parent["img"].document; - doc.open(); - doc.write("<html><body>"); - - // get list of all selected elements - var ids = tree.getAllChecked().split(','); - // loop over all elements and write <img> tag into frame - for (var i in ids) { - var imgPath = tree.getUserData(ids[i],"img"); - if (imgPath != undefined) { - doc.write('<img src="'); - doc.write(imgPath); - doc.write('"'); - } - } - doc.write("</body></html>"); - doc.close() - } - - // clear all selected items - function clearAll() { - for (var i in tree.getAllChecked().split(',')) { - tree.setCheck(i,false); - } - } - </script> - - </body> -</html> diff --git a/Trigger/TrigValidation/TrigValTools/src/TRoot2Html.cxx b/Trigger/TrigValidation/TrigValTools/src/TRoot2Html.cxx deleted file mode 100644 index 93d24229bec67448e8868a90acab6977175e5fc6..0000000000000000000000000000000000000000 --- a/Trigger/TrigValidation/TrigValTools/src/TRoot2Html.cxx +++ /dev/null @@ -1,211 +0,0 @@ -/* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration -*/ - -/** - * @file TRoot2Html.cxx - * @brief TRoot2Html implementation - * @author Frank Winklmeier - * - * $Id: TRoot2Html.cxx,v 1.1 2008-07-28 11:02:00 fwinkl Exp $ - */ - -#include "TrigValTools/TRoot2Html.h" - -#include <iostream> -#include <sstream> -#include "TError.h" -#include "TClass.h" -#include "TH1.h" -#include "TFile.h" -#include "TCanvas.h" -#include "TSystem.h" -#include "TKey.h" -#include "TPRegexp.h" - -using namespace std; - -TRoot2Html::TRoot2Html() : - m_nodeId(1), - m_showFullFileName(kFALSE) -{ - setOutputDir("./"); - setImageSize(400,400); -} - -TRoot2Html::TRoot2Html(const TRoot2Html& other): - TMultiFileLooper(other), - m_imgHeight(other.m_imgHeight), - m_imgWidth(other.m_imgWidth), - m_nodeId(other.m_nodeId), - m_showFullFileName(other.m_showFullFileName) -{ -} - -void TRoot2Html::beginJob() -{ - m_xml.open(m_outDir+"/tree.xml"); - if (!m_xml) { - cout << "Cannot write to directory " << m_outDir << endl; - return; - } - - m_xml << "<?_xml version='1.0' encoding='iso-8859-1'?>" << endl; - m_xml << "<!-- This file was auto generated by root2html -->" << endl; - m_xml << "<!-- Use it with the dhtmlxTree component (http://www.scbr.com/docs/products/dhtmlxTree) -->" << endl; - m_xml << "<tree id=\"0\">" << endl; - m_nodeId = 1; -} - -void TRoot2Html::endJob() -{ - m_xml << "</tree>" << endl; - m_xml.close(); -} - - -void TRoot2Html::beforeFile() -{ - TString treeNodeName; - if (m_showFullFileName) treeNodeName = file()->GetName(); - else treeNodeName = gSystem->BaseName(file()->GetName()); - - m_xml << "<!-- Start of " << treeNodeName << " -->" << endl; - m_xml << xmlTreeItem(treeNodeName).Data() << endl; - - // Create output directory - gSystem->mkdir(m_outDir+"/img", true); -} - -void TRoot2Html::afterFile() -{ - m_xml << xmlTreeItemClose().Data() << endl; -} - - -void TRoot2Html::beforeDir() -{ - TString s(getPathFromDir(*gDirectory)); - TString imgDir = TString(m_outDir) + "/img/" + s; - gSystem->mkdir(imgDir, true); - - m_xml << xmlTreeItem(gDirectory->GetName()).Data() << endl; -} - -void TRoot2Html::afterDir() -{ - m_xml << xmlTreeItemClose().Data() << endl; -} - - -void TRoot2Html::processKey(TDirectory& dir, TKey& key) -{ - dir.cd(); - - TObject* obj = key.ReadObj(); - if (obj->IsA()->InheritsFrom("TH1")) { - m_xml << xmlTreeItem(key.GetName()).Data() << endl; - TString imgPath = hist2Png(*gDirectory, key.GetName()); - if (imgPath!="") { - m_xml << xmlUserData("img",imgPath).Data() << endl; - } - m_xml << xmlTreeItemClose().Data() << endl; - } -} - - -// Save histogram 'name' from 'dir' in 'm_outDir/img' -// Return "" on error otherwise image path relative to m_outDir -TString TRoot2Html::hist2Png(TDirectory& dir, const TString& name) -{ - TH1* h = (TH1*)dir.Get(name); - if (h==0) { - cout << "hist2Png: Cannot load histogram " << name << endl; - return ""; - } - - TCanvas c("c","c",m_imgWidth,m_imgHeight); - TString options(getDrawOptions(*h)); - if (m_verbose) cout << "Drawing histogram " << h->GetName() - << " (" << h->ClassName() << ") with options '" - << options << "'" << endl; - h->Draw(options); - TString s(getPathFromDir(dir)); - TString pngName = "img/" + s + "/" + name + ".png"; - - // Suppress the info message when saving file - Int_t oldIgnoreLevel = gErrorIgnoreLevel; - if (!m_verbose) gErrorIgnoreLevel = kWarning; - c.SaveAs(m_outDir+"/"+pngName); - - gErrorIgnoreLevel = oldIgnoreLevel; - - return pngName; -} - - -// Set draw options for all histograms matching re -void TRoot2Html::addDrawOptions(const char* regexp, const char* options) -{ - if (regexp && options) { - TPRegexp* re = new TPRegexp(regexp); - if (re) m_drawOptions.push_back(std::pair<TPRegexp*,TString>(re,options)); - } -} - -void TRoot2Html::addClassDrawOptions(const char* regexp, const char* options) -{ - if (regexp && options) { - TPRegexp* re = new TPRegexp(regexp); - if (re) m_classDrawOptions.push_back(std::pair<TPRegexp*,TString>(re,options)); - } -} - - -// return draw options for specified histogram -TString TRoot2Html::getDrawOptions(const TH1& h) -{ - TString options(""); - - // First check if we have class wide draw options for this histogram - vector< pair<TPRegexp*,TString> >::iterator iter; - for (iter=m_classDrawOptions.begin(); iter!=m_classDrawOptions.end(); iter++) { - if (iter->first->Match(h.ClassName())>0) { - options = iter->second; - break; - } - } - - // Check if any regexp matches the histogram name - for (iter=m_drawOptions.begin(); iter!=m_drawOptions.end(); iter++) { - if (iter->first->Match(h.GetName())>0) { - options = iter->second; - break; - } - } - - return options; -} - -// Tree node with text and id -TString TRoot2Html::xmlTreeItem(const char* text) -{ - TString s; - s.Form("<item text=\"%s\" id=\"%d\">",text,m_nodeId); - m_nodeId++; - return s; -} - -// Tree node close -TString TRoot2Html::xmlTreeItemClose() -{ - return "</item>"; -} - -// User data for tree node -TString TRoot2Html::xmlUserData(const char* name, const char* data) -{ - TString s; - s.Form("<userdata name=\"%s\">%s</userdata>",name,data); - return s; -} diff --git a/Trigger/TrigValidation/TrigValTools/test/test_rootcomp.C b/Trigger/TrigValidation/TrigValTools/test/test_rootcomp.C new file mode 100644 index 0000000000000000000000000000000000000000..bd3266216a70822353c0e9da92fc1afcad215daf --- /dev/null +++ b/Trigger/TrigValidation/TrigValTools/test/test_rootcomp.C @@ -0,0 +1,36 @@ +// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +// Create two ROOT files with histograms used in test_rootcomp.sh +{ + // Histogram for both files: + TH1D h1("h1", "", 10, 0, 10); + h1.Fill(5); + { + TFile f("hist1.root", "RECREATE"); + h1.Write(); + + TH1D hr("hrandom", "", 10, 0, 10); + hr.FillRandom("gaus", 1000); + + TH1D hl("hlabel", "", 5, 0, 5); + hl.Fill("a", 1); + hl.Fill("b", 2); + + TH1D h2("hextra", "", 10, 0, 10); + + f.Write(); + } + + { + TFile f("hist2.root", "RECREATE"); + h1.Write(); + + TH1D hr("hrandom", "", 10, 0, 10); + hr.FillRandom("gaus", 1000); + + TH1D hl("hlabel", "", 4, 0, 4); // one less (empty) bin than above + hl.Fill("b", 2); + hl.Fill("a", 1); + + f.Write(); + } +} diff --git a/Trigger/TrigValidation/TrigValTools/test/test_rootcomp.sh b/Trigger/TrigValidation/TrigValTools/test/test_rootcomp.sh new file mode 100755 index 0000000000000000000000000000000000000000..9ee20934588ad0d322c8fc5687147f30f2865456 --- /dev/null +++ b/Trigger/TrigValidation/TrigValTools/test/test_rootcomp.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# +# Unit test for rootcomp.py + +if [ -z "$1" ]; then + echo "Usage: $0 root.C" + exit 1 +fi + +# Helpers: +assert_pass() { + eval $@ || exit 1 +} + +assert_fail() { + eval $@ && exit 1 +} + +# Create histogram files: +assert_pass root -l -b -n -q $1 + +# Check default options: +assert_pass rootcomp.py hist1.root hist1.root +assert_pass test -f rootcomp.root +assert_pass test -f rootcomp.ps + +# Default options for the following specific tests: +opts="--noSkipList --noPS --noRoot" + +# Check regular histogram: +assert_pass rootcomp.py hist1.root hist2.root $opts --select h1 + +# Check label sorting: +assert_pass rootcomp.py hist1.root hist2.root $opts --skip hrandom --sortLabels + +# Check failure for random histogram: +assert_fail rootcomp.py hist1.root hist2.root $opts --sortLabels + +# Missing references: +assert_fail rootcomp.py hist2.root hist1.root $opts --skip hrandom --sortLabels +assert_pass rootcomp.py hist2.root hist1.root $opts --skip hrandom --sortLabels --ignoreMissingRef + +# If we get here all tests succeeded: +exit 0 diff --git a/Trigger/TrigValidation/TrigValTools/test/test_unit_trigvalsteering.py b/Trigger/TrigValidation/TrigValTools/test/test_unit_trigvalsteering.py index 8d8958e2b9c6d162ba73dba9d634f7139cefbc86..b77f263e9cfaa970f25fcb606a385a5c3d1c6015 100755 --- a/Trigger/TrigValidation/TrigValTools/test/test_unit_trigvalsteering.py +++ b/Trigger/TrigValidation/TrigValTools/test/test_unit_trigvalsteering.py @@ -1,5 +1,6 @@ #!/usr/bin/env python - +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# # This is not an ART test. This is a unit test of the framework used for # steering Trigger ART tests.