diff --git a/Trigger/TrigValidation/TrigValTools/CMakeLists.txt b/Trigger/TrigValidation/TrigValTools/CMakeLists.txt index 81fe27447d39a72dfa3298da4c4c6374f6116ce5..7eb8cae993f06f84f8fac26c2ebe03ace7245b71 100644 --- a/Trigger/TrigValidation/TrigValTools/CMakeLists.txt +++ b/Trigger/TrigValidation/TrigValTools/CMakeLists.txt @@ -34,3 +34,7 @@ atlas_add_test( rootcomp SCRIPT test/test_rootcomp.sh ${CMAKE_CURRENT_SOURCE_DIR}/test/test_rootcomp.C PROPERTIES TIMEOUT 450 POST_EXEC_SCRIPT nopost.sh ) + +atlas_add_test( chainDump + SCRIPT test/test_chainDump.sh ${CMAKE_CURRENT_SOURCE_DIR}/test/test_chainDump.C + LOG_IGNORE_PATTERN "Processing.*test_chainDump" ) diff --git a/Trigger/TrigValidation/TrigValTools/bin/chainDump.py b/Trigger/TrigValidation/TrigValTools/bin/chainDump.py index dfa4f637d7d812cbe1c6a96853ef73f53d985657..af98ec9f7f78394620d58cb82993f730b12c283d 100755 --- a/Trigger/TrigValidation/TrigValTools/bin/chainDump.py +++ b/Trigger/TrigValidation/TrigValTools/bin/chainDump.py @@ -45,11 +45,13 @@ def get_parser(): help='Save outputs also to a json file with the given name or %(const)s if no name is given') parser.add_argument('--fracTolerance', metavar='FRAC', + type=float, default=0.001, help='Tolerance as a fraction, default = %(default)s. ' 'Flagged diffs must exceed all tolerances') parser.add_argument('--intTolerance', metavar='NUM', + type=int, default=2, help='Tolerance as a number of counts, default = %(default)s. ' 'Flagged diffs must exceed all tolerances') @@ -258,13 +260,14 @@ def print_counts(json_dict): dump_lines = [] for item_name, item_counts in counts.items(): v = item_counts['count'] - line = ' {name:{nw}s} {val:>{w}d}'.format(name=item_name, val=v, nw=name_width, w=column_width) + line = ' {name:{nw}s} {val:>{w}s}'.format(name=item_name, val=str(v), nw=name_width, w=column_width) if not no_ref: ref_v = item_counts['ref_count'] diff = item_counts['ref_diff'] - line += ' {val:>{w}d}'.format(val=ref_v, w=column_width) + line += ' {val:>{w}s}'.format(val=str(ref_v), w=column_width) if diff: line += ' <<<<<<<<<<' + dump_lines.append(line) logging.info('Writing %s counts from histogram %s:\n%s', text_name, hist_name, '\n'.join(dump_lines)) @@ -343,7 +346,7 @@ def main(): if len(in_hists) == 0: logging.error('No count histograms could be loaded.') return 1 - logging.info('Loaded count histograms: %s', in_hists.keys()) + logging.info('Loaded count histograms: %s', list(in_hists.keys())) in_total_hists = load_histograms(in_file, args.totalHists) if len(in_total_hists) == 0: @@ -359,7 +362,7 @@ def main(): ref_total = None if args.referenceFile: ref_hists = load_histograms(ref_file, args.countHists) - logging.info('Loaded reference count histograms: %s', ref_hists.keys()) + logging.info('Loaded reference count histograms: %s', list(ref_hists.keys())) missing_refs = [k for k in in_hists.keys() if k not in ref_hists.keys()] if len(missing_refs) > 0: logging.error('Count histogram(s) %s missing in the reference', missing_refs) @@ -368,9 +371,9 @@ def main(): if len(ref_total_hists) == 0: logging.error('No total-events reference histogram could be loaded') return 1 - ref_total = ref_total_hists.values()[0].GetEntries() + ref_total = list(ref_total_hists.values())[0].GetEntries() logging.info('Loaded total-events reference histogram %s, number of events: %d', - ref_total_hists.keys()[0], ref_total) + list(ref_total_hists.keys())[0], ref_total) ################################################## # Extract counts from histograms diff --git a/Trigger/TrigValidation/TrigValTools/share/chainDump.ref b/Trigger/TrigValidation/TrigValTools/share/chainDump.ref new file mode 100644 index 0000000000000000000000000000000000000000..341afb013671ecf3d2ff37e8b9f9ec97d78742ff --- /dev/null +++ b/Trigger/TrigValidation/TrigValTools/share/chainDump.ref @@ -0,0 +1,36 @@ + +Info in <test_chainDump>: Creating test file testChainDump1.root +Info in <test_chainDump>: Creating test file testChainDump2.root +INFO Loaded count histograms: ['chains', 'decisions'] +INFO Loaded total-events histogram total, number of events: 100 +INFO Loaded reference count histograms: ['chains', 'decisions'] +INFO Loaded total-events reference histogram total, number of events: 100 +INFO Comparing counts to reference +INFO HLTChain has 1 item(s) out of tolerance: + HLT_testChain1 26 5 +INFO HLTDecision has 7 item(s) out of tolerance: + HLT_testChain1_Step0 96 18 + HLT_testChain1_Step1 66 10 + HLT_testChain1_Step2 57 7 + HLT_testChain2_Step1 101 53 + HLT_testChain3_Step0 76 179 + HLT_testChain3_Step1 92 163 + HLT_testChain3_Step2 96 112 +INFO Writing total event count to file TotalEventsProcessed.txt +INFO Writing counts from histogram chains to file HLTChain.txt +INFO Writing counts from histogram decisions to file HLTDecision.txt +INFO Writing results to chainDump.json +100 +HLT_testChain1 26 5 <<<<<<<<<< +HLT_testChain2 30 40 +HLT_testChain3 62 52 +HLT_testChain1_Step0 96 18 <<<<<<<<<< +HLT_testChain1_Step1 66 10 <<<<<<<<<< +HLT_testChain1_Step2 57 7 <<<<<<<<<< +HLT_testChain2_Step0 82 86 +HLT_testChain2_Step1 101 53 <<<<<<<<<< +HLT_testChain2_Step2 71 72 +HLT_testChain3_Step0 76 179 <<<<<<<<<< +HLT_testChain3_Step1 92 163 <<<<<<<<<< +HLT_testChain3_Step2 96 112 <<<<<<<<<< +{"TotalEventsProcessed": {"hist_name": "total", "count": 100, "ref_count": 100}, "HLTChain": {"hist_name": "chains", "counts": {"HLT_testChain1": {"count": 26, "ref_count": 5, "ref_diff": true}, "HLT_testChain2": {"count": 30, "ref_count": 40, "ref_diff": false}, "HLT_testChain3": {"count": 62, "ref_count": 52, "ref_diff": false}}}, "HLTDecision": {"hist_name": "decisions", "counts": {"HLT_testChain1_Step0": {"count": 96, "ref_count": 18, "ref_diff": true}, "HLT_testChain1_Step1": {"count": 66, "ref_count": 10, "ref_diff": true}, "HLT_testChain1_Step2": {"count": 57, "ref_count": 7, "ref_diff": true}, "HLT_testChain2_Step0": {"count": 82, "ref_count": 86, "ref_diff": false}, "HLT_testChain2_Step1": {"count": 101, "ref_count": 53, "ref_diff": true}, "HLT_testChain2_Step2": {"count": 71, "ref_count": 72, "ref_diff": false}, "HLT_testChain3_Step0": {"count": 76, "ref_count": 179, "ref_diff": true}, "HLT_testChain3_Step1": {"count": 92, "ref_count": 163, "ref_diff": true}, "HLT_testChain3_Step2": {"count": 96, "ref_count": 112, "ref_diff": true}}}} diff --git a/Trigger/TrigValidation/TrigValTools/test/test_chainDump.C b/Trigger/TrigValidation/TrigValTools/test/test_chainDump.C new file mode 100644 index 0000000000000000000000000000000000000000..560451e28e3282f5efaf2e4795dccfd5ed45679b --- /dev/null +++ b/Trigger/TrigValidation/TrigValTools/test/test_chainDump.C @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +void fillBin(TH2& h, const char* xlabel, const char* ylabel, size_t n) { + h.SetBinContent(h.GetXaxis()->FindBin(xlabel), h.GetYaxis()->FindBin(ylabel), n); +} + +void makeTestFile(const char* fileName) { + TFile f(fileName, "RECREATE"); + size_t nTotal = 100; + + TH1D total("total", "", 10, 0, 10); + total.FillRandom("gaus", nTotal); + + TH2D chains("chains", "chains;chain;step", 3, 0, 3, 6, 0, 6); + TH2D decisions("decisions", "decisions;chain;step", 3, 0, 3, 6, 0, 6); + for (TH2D* h : {&chains, &decisions}) { + h->GetXaxis()->SetBinLabel(1, "HLT_testChain1"); + h->GetXaxis()->SetBinLabel(2, "HLT_testChain2"); + h->GetXaxis()->SetBinLabel(3, "HLT_testChain3"); + h->GetYaxis()->SetBinLabel(1, "L1"); + h->GetYaxis()->SetBinLabel(2, "AfterPS"); + h->GetYaxis()->SetBinLabel(3, "Step 0"); + h->GetYaxis()->SetBinLabel(4, "Step 1"); + h->GetYaxis()->SetBinLabel(5, "Step 2"); + h->GetYaxis()->SetBinLabel(6, "Output"); + } + for (size_t iChain=1; iChain<4; ++iChain) { + TString chainName = TString::Format("HLT_testChain%lu", iChain); + size_t nInput = gRandom->Uniform(nTotal); + size_t nOutput = gRandom->Uniform(nInput/2, nInput); + fillBin(chains, chainName.Data(), "L1", nInput); + fillBin(chains, chainName.Data(), "AfterPS", nInput); + fillBin(chains, chainName.Data(), "Output", nOutput); + for (size_t iStep=0; iStep<3; ++iStep) { + TString stepName = TString::Format("Step %lu", iStep); + size_t nStepMin = (8-iStep)*nInput/10; + size_t nStepMax = (9-iStep)*nInput/10; + size_t nStep = gRandom->Uniform(nStepMin, nStepMax); + size_t nDecisions = gRandom->Uniform(nStepMax, 2*nInput); + fillBin(chains, chainName.Data(), stepName.Data(), nStep); + fillBin(decisions, chainName.Data(), stepName.Data(), nDecisions); + } + } + + f.Write(); +} + +void test_chainDump() { + delete gRandom; + gRandom = new TRandom3(1234); // arbitrary fixed seed + Info("test_chainDump", "Creating test file testChainDump1.root"); + makeTestFile("testChainDump1.root"); + gRandom->SetSeed(12345); // different arbitrary fixed seed + Info("test_chainDump", "Creating test file testChainDump2.root"); + makeTestFile("testChainDump2.root"); +} diff --git a/Trigger/TrigValidation/TrigValTools/test/test_chainDump.sh b/Trigger/TrigValidation/TrigValTools/test/test_chainDump.sh new file mode 100755 index 0000000000000000000000000000000000000000..c3e8aad0d581d339062bba5d73429cfb75ce92ba --- /dev/null +++ b/Trigger/TrigValidation/TrigValTools/test/test_chainDump.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# +# Unit test for chainDump.py + +if [ -z "$1" ]; then + echo "Usage: $0 root.C" + exit 1 +fi + +# Helpers: +assert_pass() { + eval $@ || exit 1 +} + +assert_fail() { + eval $@ && exit 1 +} + +# Clean up files +rm -f testChainDump1.root testChainDump2.root TotalEventsProcessed.txt HLTChain.txt HLTDecision.txt chainDump.json + +# Create histogram files: +assert_pass root -l -b -n -q $1 + +# Run chainDump +assert_fail chainDump.py --json --fracTolerance=0.1 --intTolerance=10 \ +--totalHists total --countHists chains decisions \ +--histDict chains:HLTChain decisions:HLTDecision \ +-r testChainDump1.root -f testChainDump2.root + +# Print output files +assert_pass cat TotalEventsProcessed.txt +assert_pass cat HLTChain.txt +assert_pass cat HLTDecision.txt +assert_pass cat chainDump.json + +# If we get here all tests succeeded: +exit 0