EGS Brachy
An egs++ user code for rapid brachytherapy calculations
Loading...
Searching...
No Matches
/Users/marc/Developer/EGSnrc/HEN_HOUSE/user_codes/egs_brachy/egs_brachy/run_tests.py
Go to the documentation of this file.
1import glob
2import os
3import re
4import shutil
5import sys
6import traceback
7from subprocess import PIPE, Popen
8
9VERBOSE = False
10if "-v" in sys.argv:
11 VERBOSE = True
12 sys.argv.remove("-v")
13
14timing_hard_fail = "--timing-hard-fail" in sys.argv
15
16EGS_HOME = os.environ["EGS_HOME"]
17EGS_BRACHY = os.path.join(EGS_HOME, "egs_brachy")
18
19USER_CODE = "egs_brachy"
20TEST_EGSINP_FILE = "eb_test_run"
21TEST_EGSINP_PATH_ROOT = os.path.join(EGS_BRACHY, TEST_EGSINP_FILE)
22TEST_EGSINP_PATH = TEST_EGSINP_PATH_ROOT + ".egsinp"
23
24
25PASS_FMT = "%(pass_fail)s - %(test)s - ran in %(actual_time).3G s/MHz (%(real_time).3G s)"
26
27TIMING_WARN_FMT = """%(pass_fail)s - %(test)s
28 Timing: %(timing_pass_fail)s
29 Limit: %(time_limit).3G s/MHz
30 Actual : %(actual_time).3G s/MHz
31 Results: %(results_pass_fail)s
32"""
33
34FAIL_FMT = """%(pass_fail)s - %(test)s
35 Timing: %(timing_pass_fail)s
36 Limit: %(time_limit).3G s/MHz
37 Actual : %(actual_time).3G s/MHz
38 Results: %(results_pass_fail)s
39 Expected: %(expected_results)s
40 Actual : %(actual_results)s
41"""
42
43cpu_speed_cmd = """grep -i "cpu mhz" /proc/cpuinfo | tail -1 | awk -F ":" '{print $2}'"""
44
45try:
46
47 try:
48 CPU_MHZ = float(os.environ["CPU_MHZ"])
49 source = "CPU_MHZ env variable"
50 except (ValueError, KeyError):
51 #stdin, stdout, stderr = os.popen3(cpu_speed_cmd)
52
53 p = Popen(cpu_speed_cmd, shell=True,
54 stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
55 (stdin, stdout, stderr) = (p.stdin, p.stdout, p.stderr)
56 CPU_MHZ = float(stdout.read())
57 source = "/proc/cpuinfo"
58
59 print(("CPU speed read from %s as %f MHz" % (source, CPU_MHZ)))
60
61except (ValueError, TypeError):
62 sys.exit(
63 "Unable to determine CPU speed. You must set CPU_MHZ "
64 "environment variable before running the test suite."
65 )
66
67TIMING_MARGIN = 1.05
68
69
70def dyn_import(name):
71 mod = __import__(name)
72 components = name.split('.')
73 for comp in components[1:]:
74 mod = getattr(mod, comp)
75 return mod
76
77
78def create_egsinp(test_module):
79 egsinp = test_module.EGSINP
80 path_components = test_module.__name__.split(".") + [egsinp]
81 src = os.path.join(*path_components)
82 shutil.copy(src, TEST_EGSINP_PATH)
83
84
85def find_cpu_time(egslst):
86 try:
87 return float(re.findall("Finished simulation.*?CPU time:(.*?)s.*", egslst, re.S)[0])
88 except:
89 return None
90
91
93
94 command = "%s -i %s" % (USER_CODE, TEST_EGSINP_FILE)
95 p = Popen(command, shell=True,
96 stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
97 (stdin, stdout, stderr) = (p.stdin, p.stdout, p.stderr)
98 egslst = stdout.read()
99 errors = stderr.read()
100 if not isinstance(egslst, str):
101 egslst = egslst.decode("utf-8")
102 errors = errors.decode("utf-8")
103 cpu_time = find_cpu_time(egslst) or -1
104
105 return egslst, errors, cpu_time/CPU_MHZ
106
107
109 to_clean = glob.glob(TEST_EGSINP_PATH_ROOT+".*")
110 for f in to_clean:
111 # sanity check to make sure we're not deleting anything outside of this directory
112 file_is_in_current_dir = os.path.dirname(f) == os.path.dirname(os.path.abspath(__file__))
113 if file_is_in_current_dir:
114 try:
115 os.remove(f)
116 except PermissionError as e:
117 print(e)
118 print("{} was not deleted because of a permission error.".format(os.path.basename(f)))
119
120
122 if len(sys.argv) > 1:
123 tests = glob.glob(os.path.join(os.path.normpath(sys.argv[1]), "__init__.py"))
124 else:
125 tests = glob.glob("eb_tests/*/__init__.py")
126
127 return [x.replace(os.path.join(os.path.sep, "__init__.py"), "").replace(os.path.sep, ".") for x in tests]
128
129
131
132 pass_count = 0
133 warn_count = 0
134 all_tests = find_tests()
135 for t in all_tests:
136
137 print(("Running test '%s'..." % (t,)))
138 test_module = dyn_import(t)
139 create_egsinp(test_module)
140
141 time_limit = test_module.TIME_LIMIT_S_PER_MHZ
142
143 try:
144 egslst, errors, actual_time = run_simulation()
145 if VERBOSE:
146 print(egslst)
147 print(errors)
148 if actual_time < 0:
149 print("Simulation did not complete. egs_brachy crash likely")
150 continue
151 results_pass, actual_results, expected_results = test_module.compare_results(egslst, TEST_EGSINP_FILE)
152 except:
153 print(("Exception while running test '%s'..." % t))
154 traceback.print_exc()
155 continue
156
157 timing_passes = actual_time <= TIMING_MARGIN*time_limit
158 if not timing_passes and not timing_hard_fail:
159 warn_count += 1
160
161 passes = results_pass and timing_passes if timing_hard_fail else results_pass
162
163 pass_count += int(passes)
164
165 if results_pass and timing_passes:
166 fmt = PASS_FMT
167 elif results_pass:
168 fmt = TIMING_WARN_FMT
169 else:
170 fmt = FAIL_FMT
171
172 print((fmt % {
173 "test": t,
174 "pass_fail": ["FAIL", "PASS"][passes],
175 "time_limit": time_limit,
176 "actual_time": actual_time,
177 "real_time": actual_time*CPU_MHZ,
178 "timing_pass_fail": ["FAIL", "PASS"][timing_passes],
179 "expected_results": expected_results,
180 "actual_results": actual_results,
181 "results_pass_fail": ["FAIL", "PASS"][results_pass],
182 }))
183
184 cleanup()
185
186 print(("="*80))
187 print(("Tests finished %d/%d passed with %d warnings" % (pass_count, len(all_tests), warn_count)))
188
189if __name__ == "__main__":
dyn_import(name)
Definition run_tests.py:70
find_cpu_time(egslst)
Definition run_tests.py:85
create_egsinp(test_module)
Definition run_tests.py:78
run_all_tests()
Definition run_tests.py:130
run_simulation()
Definition run_tests.py:92