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