-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcoverage.py
106 lines (83 loc) · 2.56 KB
/
coverage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import math
import numpy as np
WCAG_LEVELS = [3, 4.5, 7]
WCAG_LEVELS_TWEAKED = [3.5, 5.5, 8]
WCAG4_LEVELS = [1.6, 2.5, 3.9, 6, 9, 13]
APCA_LEVELS = [15, 30, 45, 60, 75, 90]
def wcag_y(color):
c = color / 255
c = np.where(c < 0.04045, c / 12.92, ((c + 0.055) / 1.055) ** 2.4)
return 0.2126 * c[:, 0] + 0.7152 * c[:, 1] + 0.0722 * c[:, 2]
def wcag_contrast(yfg, ybg, ambient=0.05):
c = (ybg + ambient) / (yfg + ambient)
c = np.where(c < 1, 1 / c, c)
y0 = ambient
y1 = 1 + ambient
return c ** math.log(21, y1 / y0)
def apca_y(color):
c = color / 255
c **= 2.4
y = 0.2126729 * c[:, 0] + 0.7151522 * c[:, 1] + 0.0721750 * c[:, 2]
y += np.where(y < 0.022, 0.022 - y, 0) ** 1.414
return y
def apca_contrast(yfg, ybg):
jfg = yfg ** np.where(ybg > yfg, 0.57, 0.62)
jbg = ybg ** np.where(ybg > yfg, 0.56, 0.65)
c = (jbg - jfg) * 1.14
c = np.where(np.abs(c) < 0.1, 0, np.where(c > 0, c - 0.027, c + 0.027))
return np.abs(c) * 100
def iter_levels(levels):
for i in range(len(levels) + 1):
if i == 0:
yield -math.inf, levels[i]
elif i == len(levels):
yield levels[i - 1], math.inf
else:
yield levels[i - 1], levels[i]
def print_row(row, sep=' | '):
_row = [''] + [f'{x:.1f}' for x in row] + ['']
_row = [f'{s: >7}' for s in _row]
print(sep.join(_row).strip())
def print_table(rows):
for row in rows:
print_row(row + [sum(row)])
r = np.array(rows)
totals = [sum(r[:, i]) for i in range(r.shape[1])]
if len(rows) == len(rows[0]):
totals.append(sum(rows[i][i] for i in range(len(rows))))
else:
totals.append(
rows[0][0] + rows[0][1] + rows[0][2]
+ rows[1][3]
+ rows[2][4]
+ rows[3][5] + rows[3][6]
)
print_row(totals)
print()
if __name__ == '__main__':
size = 20_000
fg = np.random.randint(0, 256, size=(size, 3))
bg = np.random.randint(0, 256, size=(size, 3))
apca_yfg = apca_y(fg)
apca_ybg = apca_y(bg)
apca = apca_contrast(apca_yfg, apca_ybg)
apcai = apca_contrast(apca_ybg, apca_yfg)
wcag_yfg = wcag_y(fg)
wcag_ybg = wcag_y(bg)
wcag = wcag_contrast(wcag_yfg, wcag_ybg)
wcag4 = wcag_contrast(wcag_yfg, wcag_ybg, 0.4)
for values1, levels1, values2, levels2 in [
(wcag, WCAG_LEVELS, apca, APCA_LEVELS),
(wcag, WCAG_LEVELS_TWEAKED, apca, APCA_LEVELS),
(wcag4, WCAG4_LEVELS, apca, APCA_LEVELS),
(apcai, APCA_LEVELS, apca, APCA_LEVELS),
]:
rows = []
for lower1, upper1 in iter_levels(levels1):
rows.append([])
a = (lower1 <= values1) & (values1 < upper1)
for lower2, upper2 in iter_levels(levels2):
b = (lower2 <= values2) & (values2 < upper2)
v = sum(a & b) / size * 100
rows[-1].append(v)
print_table(rows)