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

1from typing import Generator 

2from pathlib import Path 

3import re 

4 

5import numpy as np 

6 

7 

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) 

20 

21 

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()) 

28 

29 

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() 

48 

49 

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) 

56 

57 

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 

75 

76 

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 

82 

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 

99 

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 

106 

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 

129 

130 

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]))