Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2@file
3@brief Plotting helpers
4"""
5import numpy
6from ..benchmark import enumerate_options
9def list_col_options(df, cols):
10 """
11 @param df dataframe
12 @param cols cols to look for options
13 @return options
15 .. exref::
16 :title: Enumerate all coordinates
18 .. runpython::
19 :showcode:
21 from pymlbenchmark.plotting.plot_helper import list_col_options
22 from pandas import DataFrame
23 df = DataFrame([
24 dict(i=1, t='aa', x=0.5),
25 dict(i=2, t='bb', x=0.5),
26 dict(i=2, t='aa', x=0.5),
27 ])
28 for opt in list_col_options(df, ['i', 't']):
29 print(opt)
31 # if None...
32 print(list_col_options(df, None))
33 """
34 if cols is None:
35 return [None]
37 if not isinstance(cols, (tuple, list)):
38 cols = [cols]
39 elif cols[0] is None:
40 return [None]
42 options = {k: list(sorted(set(df[k]))) for k in cols}
43 return list(enumerate_options(options))
46def filter_df_options(df, options):
47 """
48 Filters out rows from a dataframe.
50 @param df dataframe
51 @param options options
52 @return filtered dataframe
54 .. runpython::
55 :showcode:
57 from pymlbenchmark.plotting.plot_helper import filter_df_options
58 from pandas import DataFrame
59 df = DataFrame([
60 dict(i=1, t='aa', x=0.5),
61 dict(i=2, t='bb', x=0.5),
62 dict(i=2, t='aa', x=0.5),
63 ])
65 sub = filter_df_options(df, {'i': 1, 't': 'aa'})
66 print(sub)
68 sub = filter_df_options(df, [None])
69 print(sub)
70 """
71 if options is None:
72 return df
73 elif isinstance(options, list):
74 if options[0] is None:
75 return df
76 else:
77 raise RuntimeError( # pragma: no cover
78 "options must be dictionary or [None] not {}".format(options))
79 for k, v in options.items():
80 df = df[df[k] == v]
81 return df
84def options2label(opt, sep=" ", format_number="{:.3g}"):
85 """
86 Converts a list of options into a label.
88 @param opt dictionary
89 @param sep separator
90 @param format_number how to format real numbers
91 @return string
93 .. runpython::
94 :showcode:
96 from pymlbenchmark.plotting.plot_helper import options2label
97 res = options2label({'i': 1, 't': 'aa', 'x': 3.145667e10})
98 print(res)
99 """
100 if opt is None:
101 return "-"
102 rows = []
103 for k, v in sorted(opt.items()):
104 if isinstance(v, (float, numpy.float64, numpy.float32)):
105 v = format_number.format(v)
106 rows.append("{}={}".format(k, v))
107 return sep.join(rows)
110def ax_position(shape, pos):
111 """
112 :epkg:`matplotlib` uses a one dimension
113 array if the number of columns or rows is 1.
114 This function makes a correction.
116 @param shape graph shape
117 @param pos graph current position
118 @return corrected position
120 .. runpython::
121 :showcode:
123 from pymlbenchmark.plotting.plot_helper import ax_position
124 print(ax_position((2, 2), (0, 0)))
125 print(ax_position((1, 2), (0, 0)))
126 """
127 res = []
128 for a, b in zip(shape, pos):
129 if a > 1:
130 res.append(b)
131 return tuple(res)
134def plt_colors():
135 """
136 Returns :epkg:`matplotlib` colors.
138 .. runpython::
139 :showcode:
141 from pymlbenchmark.plotting.plot_helper import plt_colors
142 from pprint import pprint
143 pprint(plt_colors())
144 """
145 import matplotlib.colors as mcolors # pylint: disable=C0415
146 colors = [k.split(':')[-1] for k in mcolors.TABLEAU_COLORS]
147 for k in sorted(mcolors.CSS4_COLORS):
148 colors.append(k)
149 return colors
152def plt_styles():
153 """
154 Returns :epkg:`matplotlib` styles.
156 .. runpython::
157 :showcode:
159 from pymlbenchmark.plotting.plot_helper import plt_styles
160 from pprint import pprint
161 pprint(plt_styles())
162 """
163 return [('o', '-'), ('x', '-'), ('*', '-'), ('^', '-'),
164 ('o', '--'), ('x', '--'), ('*', '--'), ('^', '--')]
167def move_color_add(style):
168 """
169 Makes color lighter or darker
170 based on a style.
171 """
172 return {'o': 0, 'x': 80, '*': -80, '^': 120}[style]
175def move_color(color, add=2):
176 """
177 Returns a different colors, lighter or darker.
179 @param color name of something starting with ``#``
180 @param add what to add to each color,
181 positive to make it lighter
182 @return lighter column
183 """
184 if not color.startswith("#"):
185 import matplotlib.colors as mcolors # pylint: disable=C0415
186 color = mcolors.CSS4_COLORS[color]
187 rgb = tuple(int(color[1 + i * 2: 3 + i * 2], base=16) for i in range(0, 3))
188 if add > 0:
189 rgb = tuple(min(255, i + add) for i in rgb)
190 else:
191 rgb = tuple(max(0, i + add) for i in rgb)
192 return "#%02X%02X%02X" % rgb
195def remove_common_prefix(labels, drop_rename=None):
196 """
197 Removes the common prefix of a series of labels.
199 @param labels labels
200 @param drop_rename skips those labels
201 @return stripped labels
203 .. runpython::
204 :showcode:
206 from pymlbenchmark.plotting.plot_helper import remove_common_prefix
207 labels = ["x=a", "x=b"]
208 print(remove_common_prefix(labels))
209 """
210 drop_rename = set(drop_rename) if drop_rename else []
211 prefix = None
212 for label in labels:
213 if label in drop_rename:
214 continue
215 if not isinstance(label, str):
216 if isinstance(label, float) and numpy.isnan(label):
217 continue
218 return labels
219 if prefix is None:
220 prefix = label
221 elif not label.startswith(prefix):
222 begin = min(len(prefix), len(label))
223 for i in range(begin, -1, -1):
224 prefix = prefix[:i] # pylint: disable=E1136
225 if label.startswith(prefix):
226 break
227 if prefix == "":
228 return labels
229 last = len(prefix)
230 res = [(label[last:] if (isinstance(label, str) and
231 label not in drop_rename) else label)
232 for label in labels]
233 return res