Completed
Push — master ( 7b504c...b6f606 )
by Ionel Cristian
01:16
created

CustomBox._value_format()   A

Complexity

Conditions 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
1
import py
2
3
from .utils import TIME_UNITS
4
from .utils import slugify
5
6
try:
7
    from pygal.graph.box import Box
8
    from pygal.graph.graph import is_list_like
9
    from pygal.style import DefaultStyle
10
except ImportError as exc:
11
    raise ImportError(exc.args, "Please install pygal and pygaljs or pytest-benchmark[histogram]")
12
13
14
class CustomBox(Box):
15
    def _box_points(self, serie, _):
16
        return serie, [serie[0], serie[6]]
17
18
    def _value_format(self, x):
19
        return "Min: {0[0]:.4f}\n" \
20
               "Q1-1.5IQR: {0[1]:.4f}\n" \
21
               "Q1: {0[2]:.4f}\nMedian: {0[3]:.4f}\nQ3: {0[4]:.4f}\n" \
22
               "Q3+1.5IQR: {0[5]:.4f}\n" \
23
               "Max: {0[6]:.4f}".format(x[:7])
24
25
    def _format(self, x, *args):
26
        sup = super(CustomBox, self)._format
27
        if args:
28
            val = x.values
29
        else:
30
            val = x
31
        if is_list_like(val):
32
            return self._value_format(val), val[7]
33
        else:
34
            return sup(x, *args)
35
36
    def _tooltip_data(self, node, value, x, y, classes=None, xlabel=None):
37
        super(CustomBox, self)._tooltip_data(node, value[0], x, y, classes=classes, xlabel=None)
38
        self.svg.node(node, 'desc', class_="x_label").text = value[1]
39
40
41
def make_plot(benchmarks, title, adjustment):
42
    class Style(DefaultStyle):
43
        colors = ["#000000" if row["path"] else DefaultStyle.colors[1]
44
                  for row in benchmarks]
45
        font_family = 'Consolas, "Deja Vu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace'
46
47
    minimum = int(min(row["min"] * adjustment for row in benchmarks))
48
    maximum = int(max(
49
        min(row["max"], row["hd15iqr"]) * adjustment
50
        for row in benchmarks
51
    ) + 1)
52
53
    try:
54
        import pygaljs
55
    except ImportError:
56
        opts = {}
57
    else:
58
        opts = {
59
            "js": [
60
                pygaljs.uri("2.0.x", "pygal-tooltips.js")
61
            ]
62
        }
63
64
    plot = CustomBox(
65
        box_mode='tukey',
66
        x_label_rotation=-90,
67
        x_labels=["{0[name]}".format(row) for row in benchmarks],
68
        show_legend=False,
69
        title=title,
70
        x_title="Trial",
71
        y_title="Duration",
72
        style=Style,
73
        min_scale=20,
74
        max_scale=20,
75
        truncate_label=50,
76
        range=(minimum, maximum),
77
        zero=minimum,
78
        css=[
79
            "file://style.css",
80
            "file://graph.css",
81
            """inline:
82
                .tooltip .value {
83
                    font-size: 1em !important;
84
                }
85
                .axis text {
86
                    font-size: 9px !important;
87
                }
88
            """
89
        ],
90
        **opts
91
    )
92
93
    for row in benchmarks:
94
        serie = [row[field] * adjustment for field in ["min", "ld15iqr", "q1", "median", "q3", "hd15iqr", "max"]]
95
        serie.append(row["path"])
96
        plot.add("{0[fullname]} - {0[rounds]} rounds".format(row), serie)
97
    return plot
98
99
100
def make_histogram(output_prefix, name, benchmarks, unit, adjustment):
101
    if name:
102
        path = "{0}-{1}.svg".format(output_prefix, slugify(name))
103
        title = "Speed in {0} of {1}".format(TIME_UNITS[unit], name)
104
    else:
105
        path = "{0}.svg".format(output_prefix)
106
        title = "Speed in {0}".format(TIME_UNITS[unit])
107
108
    output_file = py.path.local(path).ensure()
109
110
    plot = make_plot(
111
        benchmarks=benchmarks,
112
        title=title,
113
        adjustment=adjustment,
114
    )
115
    plot.render_to_file(str(output_file))
116
    return output_file
117