ATLAS Offline Software
Loading...
Searching...
No Matches
integration_grid_tester.py
Go to the documentation of this file.
1# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
2
3from AthenaCommon import Logging
4from ...decorators import timed
5import glob
6import math
7import re
8
9
10logger = Logging.logging.getLogger("PowhegControl")
11
12
13regex_match_floats = r"[+-]? *(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?"
14# [+-]? * # first, match an optional sign (and space)
15# (?: # then match integers or f.p. mantissas:
16# \d+ # start out with a ...
17# (?:
18# \.\d* # mantissa of the form a.b or a.
19# )? # ? takes care of integers of the form a
20# |\.\d+ # mantissa of the form .b
21# )
22# (?:[eE][+-]?\d+)? # finally, optionally match an exponent
23
24
25@timed("integration grid testing")
27 """! Calculate and output integration grid quality.
28
29 Read in integration quality metrics from output files.
30 Allow any check to fail, since this output is not a critical part of generation.
31
32 @author James Robinson <james.robinson@cern.ch>
33 """
34 inclusive_xs, inclusive_xs_error, negative_weights, positive_weights, n_events, n_upper_bound_failures_xs, n_upper_bound_failures_radiation = 0, 0, 0, 0, 0, 0, 0
35 # Open stat files
36 for file_name in sum([glob.glob(_f) for _f in ["pwgstat.dat", "pwgstat-0001.dat", "pwg-stat.dat", "pwg-st3-0001-stat.dat", "pwg-0001-st3-stat.dat"]], []):
37 # Inclusive cross-section uncertainty [relative error on (total pos + |total neg|)]
38 with open(file_name, "r") as data_file:
39 try:
40 matched_lines = [line.replace("+-", "") for line in data_file if re.match(r"(.*)(btilde(.*)weights)(.*)[0-9](.*)\+\-(.*)[0-9](.*)", line)]
41 matched_lines = [re.sub(" +", " ", _l) for _l in matched_lines] # strip multiple whitespace
42 if len(matched_lines) > 0:
43 positive_weight_xs = sum([list(map(float, re.findall(regex_match_floats, line))) for line in matched_lines if "pos." in line],[])
44 negative_weight_xs = sum([list(map(float, re.findall(regex_match_floats, line))) for line in matched_lines if "|neg.|" in line], [])
45 inclusive_xs += positive_weight_xs[0] + negative_weight_xs[0]
46 inclusive_xs_error += math.sqrt(positive_weight_xs[1]**2 + negative_weight_xs[1]**2)
47 except Exception: # catch all exceptions
48 pass
49 # Negative weight test
50 with open(file_name, "r") as data_file:
51 try:
52 matched_lines = [line.replace("+-", "") for line in data_file if re.match(r"(.*)(btilde(.*)weights|Remnant cross section)(.*)[0-9](.*)\+\-(.*)[0-9](.*)", line)]
53 matched_lines = [re.sub(" +", " ", _l) for _l in matched_lines] # strip multiple whitespace
54 if len(matched_lines) > 0:
55 negative_weights += list(map(float, re.findall(regex_match_floats, [line for line in matched_lines if "btilde |neg.|" in line][0])))[0]
56 positive_weights += list(map(float, re.findall(regex_match_floats, [line for line in matched_lines if "btilde pos." in line][0])))[0]
57 positive_weights += list(map(float, re.findall(regex_match_floats, [line for line in matched_lines if "Remnant cross section" in line][0])))[0]
58 except Exception: # catch all exceptions
59 pass
60 # Open counter files
61 file_names = sum([glob.glob(_f) for _f in ["pwgcounters-st4-*.dat", "pwgcounters0*.dat"]], [])
62 if not file_names: file_names = glob.glob("pwgcounters.dat")
63 for file_name in file_names:
64 # Upper bound violations [in inclusive cross-section and generation of radiation]
65 with open(file_name, "r") as data_file:
66 try:
67 matched_lines = [line.replace("+-", "") for line in data_file if re.match(r"(.*)(btilde event|remnant event|upper bound failure)(.*)[0-9](.*)", line)]
68 matched_lines = [re.sub(" +", " ", _l) for _l in matched_lines] # strip multiple whitespace
69 if len(matched_lines) > 0:
70 n_events += sum(list(map(float, [re.findall(regex_match_floats, line)[0] for line in matched_lines if "event" in line])))
71 n_upper_bound_failures_xs += sum(list(map(float, [re.findall(regex_match_floats, line)[0] for line in matched_lines if "upper bound failure in inclusive" in line])))
72 n_upper_bound_failures_radiation += sum(list(map(float, [re.findall(regex_match_floats, line)[0] for line in matched_lines if "upper bound failure in generation" in line])))
73 except Exception: # catch all exceptions
74 pass
75
76 # Calculate test statistics
77 inclusive_xs_test = safe_percentage(inclusive_xs_error, inclusive_xs)
78 negative_weight_test = safe_percentage(negative_weights, (negative_weights + positive_weights))
79 upper_bound_test = safe_percentage((n_upper_bound_failures_xs + n_upper_bound_failures_radiation), n_events)
80 upper_bound_test_xs = safe_percentage(n_upper_bound_failures_xs, n_events)
81 upper_bound_test_radiation = safe_percentage(n_upper_bound_failures_radiation, n_events)
82
83 # Write output
84 try:
85 getattr(logger, ["warning", "info"][0.0 <= inclusive_xs_test < 1.0])("Integration test :: {:>30} : {:.2f}%".format("cross-section uncertainty", inclusive_xs_test))
86 getattr(logger, ["warning", "info"][0.0 <= negative_weight_test < 1.0])("Integration test :: {:>30} : {:.2f}%".format("negative weight fraction", negative_weight_test))
87 getattr(logger, ["warning", "info"][0.0 <= upper_bound_test < 1.0])("Integration test :: {:>30} : {:.2f}%".format("upper bound violations", upper_bound_test))
88 logger.info(" -> {:>30} : {:.2f}%".format("in inclusive cross-section", upper_bound_test_xs))
89 logger.info(" -> {:>30} : {:.2f}%".format("in generation of radiation", upper_bound_test_radiation))
90 if any((inclusive_xs_test < 0.0, inclusive_xs_test >= 1.0, negative_weight_test < 0.0, negative_weight_test >= 1.0, upper_bound_test < 0.0, upper_bound_test >= 1.0)):
91 logger.warning("Not all integration tests passed. Please ensure that physics validation is done before using this sample!")
92 except Exception: # catch all exceptions
93 pass
94
95def safe_percentage(numerator, denominator):
96 try:
97 return 100 * numerator / denominator
98 except Exception: # catch all exceptions
99 return float("nan")
STL class.
integration_grid_tester()
Calculate and output integration grid quality.