aboutsummaryrefslogtreecommitdiffstats
path: root/bench/plot.py
blob: 91b33f9620c67ffe3b0884379f6730c7d56cff58 (plain) (blame)
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/usr/bin/env python3
# See LICENSE file for copyright and license details.


# Invoke using `env XKCD_STYLE=` to for more a comical plot style.

# Invoke using `env PER_BIT=` to divide all time values by the number
# of bits that where processed. This applies to 2-dimensional data only.

# Invoke using `env VIOLIN_STYLE=` to draw violin plots rather than
# box plots. This applies to multisample 1-dimensional data only.
# If used, used `env SHOW_MEAN=` will show that mean value in place
# of the median value.

# For multisample 1-dimensional, if `env VIOLIN_STYLE=` is not used
# `env NOTCH_STYLE=`, `env PATCH_ARTIST`, and `env SHOW_MEAN` may be
# applied.


import sys, os
import matplotlib.pyplot as plot

xkcdstyle = 'XKCD_STYLE' in os.environ
if xkcdstyle:
    plot.xkcd()
fig = plot.figure()

xint = lambda x : (float(x) if '.' in x else int(x))

multiple = 1
smultiple = ''

multiples  = [1]    * len(sys.argv[1:])
smultiples = ['']   * len(sys.argv[1:])
paths      = [None] * len(sys.argv[1:])

i = 0
for arg in sys.argv[1:]:
    if arg.startswith('*'):
        multiples[i] = float(arg[1:])
        smultiples[i] = ' * ' + arg[1:]
    else:
        paths[i] = arg
    i += 1

multiples  = multiples[:i]
smultiples = smultiples[:i]
paths      = paths[:i]

xpoints = [None] * i
ypoints = [None] * i
values  = [None] * i
labels  = [None] * i

for i, path in enumerate(paths):
    with open(path, 'rb') as file:
        lines = file.read()
    lines = lines.decode('utf-8', 'strict').split('\n')
    labels[i], dim, values[i] = lines[0] + smultiples[i], int(lines[1]), lines[2:]
    if dim > 1:
        xpoints[i], values[i] = values[i][0], values[i][1:]
        xpoints[i] = [int(x) for x in xpoints[i].split(' ')]
        xpoints[i][1] += 1
        xpoints[i] = list(range(*xpoints[i]))
    if dim > 2:
        ypoints[i], values[i] = values[i][0], values[i][1:]
        ypoints[i] = [int(x) for x in ypoints[i].split(' ')]
        ypoints[i][1] += 1
        ypoints[i] = list(range(*ypoints[i]))
    values[i] = [xint(v) * multiples[i] for v in values[i] if v != '']
    if dim == 2:
        if 'PER_BIT' in os.environ:
            values[i] = [y / x for y, x in zip(values[i], xpoints[i])]

data = [[[i], (values[i], xpoints[i], ypoints[i])] for i in range(len(values))]
data.sort(key = lambda x : x[1])
merged, data = [data[0]], data[1:]
for ([i], d) in data:
    if d == merged[-1][1]:
        merged[-1][0].append(i)
    else:
        merged.append(([i], d))

xpoints = [xpoints[i[0]] for (i, _) in merged]
ypoints = [ypoints[i[0]] for (i, _) in merged]
values  = [values[i[0]]  for (i, _) in merged]
labels  = [' & '.join(labels[j] for j in i)  for (i, _) in merged]

vmin = min(min(min(v) for v in values), 0)
vmax = max(max(max(v) for v in values), 0)

if dim == 1:
    plot.ylabel('time')
    if len(values[0]) == 1:
        plot.bar(range(len(values)),
                 [vs[0] for vs in values],
                 align = 'center',
                 orientation = 'vertical',
                 tick_label = labels)
        labels = None
    elif 'VIOLIN_STYLE' in os.environ:
        plot.violinplot(values,
                        vert = True,
                        showmeans = 'SHOW_MEAN' in os.environ,
                        showmedians = 'SHOW_MEAN' not in os.environ,
                        showextrema = True)
    else:
        plot.boxplot(values,
                    vert = True,
                     notch = 'NOTCH_STYLE' in os.environ,
                     patch_artist = 'PATCH_ARTIST' in os.environ)
        if 'SHOW_MEAN' in os.environ:
            for i in range(len(values)):
                mean = sum(values[i]) / len(values[i])
                plot.plot([i + 0.75, i + 1.25], [mean, mean]);
    if labels is not None:
        plot.setp(fig.axes,
                  xticks = [x + 1 for x in range(len(values))],
                  xticklabels = labels)
elif dim == 2:
    for i in range(len(values)):
        plot.plot(xpoints[i], values[i], label = labels[i])
    plot.legend(loc = 'best')
    plot.xlabel('bits')
    plot.ylabel('time')
elif dim == 3:
    pass

plot.ylim((vmin * 1.1, vmax * 1.1))

if not xkcdstyle:
    plot.grid(True)
plot.show()