Coverage for gpaw/doctools/agts_crontab.py: 10%
105 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-20 00:19 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-20 00:19 +0000
1from typing import Generator
2from pathlib import Path
3import re
5import numpy as np
8def find_created_files(root: Path = Path()) -> Generator[Path, None, None]:
9 for path in root.glob('**/*.py'):
10 if path.parts[0] == 'build':
11 continue
12 filenames = []
13 for line in path.read_text().splitlines():
14 if not line.startswith('# web-page:'):
15 break
16 filenames += line.split(':')[1].split(',')
17 for name in filenames:
18 name = name.strip()
19 yield path.with_name(name)
22def collect_files_for_web_page(fro: Path, to: Path) -> None:
23 for path in find_created_files(fro):
24 p = to / path.relative_to(fro)
25 print(path, p)
26 p.parent.mkdir(parents=True, exist_ok=True)
27 p.write_bytes(path.read_bytes())
30def compare_all_files(root: Path,
31 references: Path) -> None:
32 errors = []
33 for path in find_created_files(root):
34 if not path.is_file():
35 print('MISSING', path)
36 continue
37 ref = references / path.relative_to(root)
38 if not ref.is_file():
39 print('MISSING', ref)
40 continue
41 err = compare_files(path, ref)
42 if err:
43 print(err, path)
44 errors.append((err, path, ref))
45 for err, path, ref in sorted(errors):
46 print(path, ref, end=' ')
47 print()
50def compare_files(p1: Path, p2: Path) -> float:
51 if p1.suffix in {'.png', '.svg'}:
52 return compare_images(p1, p2)
53 if p1.suffix == '.db':
54 return 0.0
55 return compare_text(p1, p2)
58def compare_images(p1: Path, p2: Path) -> float:
59 import PIL.Image as pil
60 a1, a2 = (np.asarray(pil.open(p)) for p in [p1, p2])
61 if a1.shape != a2.shape:
62 print(a1.shape, a2.shape)
63 return 10.0
64 d = a1 - a2
65 N = 4
66 n1, n2, _ = d.shape
67 d = d[:n1 // N * N, :n2 // N * N]
68 d = d.reshape((n1 // N, N, n2 // N, N, -1))
69 d = d.mean(axis=(1, 3))
70 error = abs(d).mean() / 255 / 4
71 if error > 0.00012:
72 print(error)
73 return error
74 return 0.0
77def compare_text(p1: Path, p2: Path) -> float:
78 t1 = p1.read_text()
79 t2 = p2.read_text()
80 if t1 == t2:
81 return 0.0
83 # (?s:...) means match also newlines
84 for r in [r'(?s:User: .*OMP_NUM_THREADS)',
85 r'(?s:Timing:.*)',
86 r'Lattice=".*pbc="',
87 r'Process memory now:.*',
88 r'iter: .*',
89 r'20..-..-.. .*:..:..\.\d*', # date
90 r'Calculating spectrum .*',
91 r'Spectrum calculated .*']:
92 t1 = re.sub(r, '', t1)
93 t2 = re.sub(r, '', t2)
94 if t1 == t2:
95 return 0.0
96 lines1 = t1.splitlines()
97 lines2 = t2.splitlines()
98 sep = ',' if p1.suffix == '.csv' else None
100 rtol = 0.001
101 atol = 1e-8
102 if 'lcao-time' in p1.name:
103 atol = 1.5
104 elif p1.name == 'TS.xyz':
105 atol = 0.02
107 for l1, l2 in zip(lines1, lines2):
108 if l1 == l2:
109 continue
110 words1 = l1.split(sep)
111 words2 = l2.split(sep)
112 if len(words1) != len(words2):
113 print(l1, l2, words1, words2, sep)
114 return 1.0
115 for w1, w2 in zip(words1, words2):
116 try:
117 f2 = float(w2)
118 except ValueError:
119 if w1 != w2:
120 print(l1, l2, w1, w2)
121 return 1.0
122 else:
123 f1 = float(w1)
124 error = abs(f1 - f2)
125 if error > atol and error / abs(f2) > rtol:
126 print(l1, l2, f1, f2)
127 return 1.0
128 return 0.0
131if __name__ == '__main__':
132 import sys
133 compare_all_files(Path(sys.argv[1]), Path(sys.argv[2]))
134 # collect_files_for_web_page(Path(sys.argv[1]), Path(sys.argv[2]))