plot.py - libzahl - big integer library
 (HTM) git clone git://git.suckless.org/libzahl
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       plot.py (4192B)
       ---
            1 #!/usr/bin/env python3
            2 # See LICENSE file for copyright and license details.
            3 
            4 
            5 # Invoke using `env XKCD_STYLE=` to for more a comical plot style.
            6 
            7 # Invoke using `env PER_BIT=` to divide all time values by the number
            8 # of bits that where processed. This applies to 2-dimensional data only.
            9 
           10 # Invoke using `env VIOLIN_STYLE=` to draw violin plots rather than
           11 # box plots. This applies to multisample 1-dimensional data only.
           12 # If used, used `env SHOW_MEAN=` will show that mean value in place
           13 # of the median value.
           14 
           15 # For multisample 1-dimensional, if `env VIOLIN_STYLE=` is not used
           16 # `env NOTCH_STYLE=`, `env PATCH_ARTIST`, and `env SHOW_MEAN` may be
           17 # applied.
           18 
           19 
           20 import sys, os
           21 import matplotlib.pyplot as plot
           22 
           23 xkcdstyle = 'XKCD_STYLE' in os.environ
           24 if xkcdstyle:
           25     plot.xkcd()
           26 fig = plot.figure()
           27 
           28 xint = lambda x : (float(x) if '.' in x else int(x))
           29 
           30 multiple = 1
           31 smultiple = ''
           32 
           33 multiples  = [1]    * len(sys.argv[1:])
           34 smultiples = ['']   * len(sys.argv[1:])
           35 paths      = [None] * len(sys.argv[1:])
           36 
           37 i = 0
           38 for arg in sys.argv[1:]:
           39     if arg.startswith('*'):
           40         multiples[i] = float(arg[1:])
           41         smultiples[i] = ' * ' + arg[1:]
           42     else:
           43         paths[i] = arg
           44     i += 1
           45 
           46 multiples  = multiples[:i]
           47 smultiples = smultiples[:i]
           48 paths      = paths[:i]
           49 
           50 xpoints = [None] * i
           51 ypoints = [None] * i
           52 values  = [None] * i
           53 labels  = [None] * i
           54 
           55 for i, path in enumerate(paths):
           56     with open(path, 'rb') as file:
           57         lines = file.read()
           58     lines = lines.decode('utf-8', 'strict').split('\n')
           59     labels[i], dim, values[i] = lines[0] + smultiples[i], int(lines[1]), lines[2:]
           60     if dim > 1:
           61         xpoints[i], values[i] = values[i][0], values[i][1:]
           62         xpoints[i] = [int(x) for x in xpoints[i].split(' ')]
           63         xpoints[i][1] += 1
           64         xpoints[i] = list(range(*xpoints[i]))
           65     if dim > 2:
           66         ypoints[i], values[i] = values[i][0], values[i][1:]
           67         ypoints[i] = [int(x) for x in ypoints[i].split(' ')]
           68         ypoints[i][1] += 1
           69         ypoints[i] = list(range(*ypoints[i]))
           70     values[i] = [xint(v) * multiples[i] for v in values[i] if v != '']
           71     if dim == 2:
           72         if 'PER_BIT' in os.environ:
           73             values[i] = [y / x for y, x in zip(values[i], xpoints[i])]
           74 
           75 data = [[[i], (values[i], xpoints[i], ypoints[i])] for i in range(len(values))]
           76 data.sort(key = lambda x : x[1])
           77 merged, data = [data[0]], data[1:]
           78 for ([i], d) in data:
           79     if d == merged[-1][1]:
           80         merged[-1][0].append(i)
           81     else:
           82         merged.append(([i], d))
           83 
           84 xpoints = [xpoints[i[0]] for (i, _) in merged]
           85 ypoints = [ypoints[i[0]] for (i, _) in merged]
           86 values  = [values[i[0]]  for (i, _) in merged]
           87 labels  = [' & '.join(labels[j] for j in i)  for (i, _) in merged]
           88 
           89 vmin = min(min(min(v) for v in values), 0)
           90 vmax = max(max(max(v) for v in values), 0)
           91 
           92 if dim == 1:
           93     plot.ylabel('time')
           94     if len(values[0]) == 1:
           95         plot.bar(range(len(values)),
           96                  [vs[0] for vs in values],
           97                  align = 'center',
           98                  orientation = 'vertical',
           99                  tick_label = labels)
          100         labels = None
          101     elif 'VIOLIN_STYLE' in os.environ:
          102         plot.violinplot(values,
          103                         vert = True,
          104                         showmeans = 'SHOW_MEAN' in os.environ,
          105                         showmedians = 'SHOW_MEAN' not in os.environ,
          106                         showextrema = True)
          107     else:
          108         plot.boxplot(values,
          109                     vert = True,
          110                      notch = 'NOTCH_STYLE' in os.environ,
          111                      patch_artist = 'PATCH_ARTIST' in os.environ)
          112         if 'SHOW_MEAN' in os.environ:
          113             for i in range(len(values)):
          114                 mean = sum(values[i]) / len(values[i])
          115                 plot.plot([i + 0.75, i + 1.25], [mean, mean]);
          116     if labels is not None:
          117         plot.setp(fig.axes,
          118                   xticks = [x + 1 for x in range(len(values))],
          119                   xticklabels = labels)
          120 elif dim == 2:
          121     for i in range(len(values)):
          122         plot.plot(xpoints[i], values[i], label = labels[i])
          123     plot.legend(loc = 'best')
          124     plot.xlabel('bits')
          125     plot.ylabel('time')
          126 elif dim == 3:
          127     pass
          128 
          129 plot.ylim((vmin * 1.1, vmax * 1.1))
          130 
          131 if not xkcdstyle:
          132     plot.grid(True)
          133 plot.show()