Cyclopts Output Classification

This notebook is used for classifying instances that take a long time. "Long" in this context is means over a minute or so.


In [503]:
from __future__ import print_function

%matplotlib inline
%load_ext autoreload
%autoreload 2

import matplotlib.pyplot as plt
import numpy as np
import tables as t
from collections import defaultdict
import os
from cyclopts import tools, analysis


The autoreload extension is already loaded. To reload it, use:
  %reload_ext autoreload

In [504]:
prefix = '../../exec/run_results/'
fname = 'combined.h5'
dirname = 'small-long-times'
f = t.open_file(os.path.join(prefix, dirname, fname), mode='r')

props = f.root.Instances.ExchangeInstProperties
samplers = f.root.ReactorRequestSampler
grps = f.root.Instances.ExchangeGroups
results = f.root.Results.General
flows = f.root.Instances.ExchangeInstSolutions

In [505]:
#samplers.description._v_names

In [506]:
cyclus_limit_hrs = 3 # time limit on a cyclus run
lb = 3 * 60 # 2 minutes in s
ub = cyclus_limit_hrs * 60 * 60 # in s
s = 'cbc'

min_iids = [x['instid'] for x in results.where("""(solver == s) & (time < lb)""")]
mid_iids = [x['instid'] for x in results.where("""(solver == s) & (time > lb) & (time < ub)""")]
max_iids = [x['instid'] for x in results.where("""(solver == s) & (time > ub)""")]

min_pids = {x['instid']: x['paramid'] for x in props.iterrows() if x['instid'] in min_iids}
mid_pids = {x['instid']: x['paramid'] for x in props.iterrows() if x['instid'] in mid_iids}
max_pids = {x['instid']: x['paramid'] for x in props.iterrows() if x['instid'] in max_iids}

min_samplers = [x[:] for x in samplers.iterrows() if x['paramid'] in min_pids.values()]
mid_samplers = [x[:] for x in samplers.iterrows() if x['paramid'] in mid_pids.values()]
max_samplers = [x[:] for x in samplers.iterrows() if x['paramid'] in max_pids.values()]

len(min_iids), len(mid_iids), len(max_iids)


Out[506]:
(3011, 16, 45)

In [507]:
def sidx(x):
    return samplers.description._v_names.index(x)

def pidx(x):
    return props.description._v_names.index(x)

constr_idx = sidx('sup_constr_val_cutoff')
rand_idx = sidx('sup_constr_val_rand')
excl_idx = sidx('exclusive_cutoff')

max_all = {}

In [508]:
def plot_vals(xrows, xkey, xval, yrows, ykey, yval, trend=False):
    x = {r[xkey]: r[xval] for r in xrows}
    y = {r[ykey]: r[yval] for r in yrows}
    x = np.array([x[k] for k in y.keys()])
    y = np.array(y.values())
    plt.scatter(x, y)
    if trend:
        m, b = np.polyfit(x, y, 1)
        fit = m * x + b
        plt.plot(x, fit, 'r-')
    plt.xlim(min(x), max(x))
    plt.ylim(min(y), max(y))

In [539]:
iids = min_iids
xrows = [x[:] for x in props.iterrows() if x['instid'] in iids] 
yrows = [x[:] for x in results.where("""solver==s""") if x['instid'] in iids] 
xkey, xval = props.description._v_names.index('instid'), props.description._v_names.index('excl_frac')
ykey, yval = results.description._v_names.index('instid'), results.description._v_names.index('time')
#print([tools.uuidhex(x[ykey]) for x in yrows if x[yval] < 82 and x[yval] > 80])
plot_vals(xrows, xkey, xval, yrows, ykey, yval)
plt.xlabel('Fraction Integer')
plt.ylabel('solution time (s)')


Out[539]:
<matplotlib.text.Text at 0x7f9b682ed790>

In [510]:
cutoffs = (set(x[constr_idx] for x in mid_samplers + max_samplers), set(x[constr_idx] for x in min_samplers))
cutoffs


Out[510]:
({0.25}, {0.25, 1.0})

In [511]:
rands = (set(x[rand_idx] for x in mid_samplers + max_samplers), set(x[rand_idx] for x in min_samplers))
rands


Out[511]:
({False, True}, {False, True})

In [512]:
excls = (set(x[excl_idx] for x in mid_samplers + max_samplers), set(x[excl_idx] for x in min_samplers))
excls


Out[512]:
({0.5, 1.0}, {-1.0, 0.5, 1.0})

In [513]:
set((x[constr_idx], x[excl_idx]) for x in min_samplers)


Out[513]:
{(0.25, -1.0), (0.25, 0.5), (0.25, 1.0), (1.0, -1.0), (1.0, 0.5), (1.0, 1.0)}

In [514]:
set((x[constr_idx], x[excl_idx]) for x in mid_samplers + max_samplers)


Out[514]:
{(0.25, 0.5), (0.25, 1.0)}

In [518]:
set((x[constr_idx], x[excl_idx], x[sidx('connection_cutoff')]) for x in max_samplers)


Out[518]:
{(0.25, 0.5, 1.0), (0.25, 1.0, 0.5), (0.25, 1.0, 1.0)}

In [519]:
set((x[constr_idx], x[excl_idx], x[sidx('n_req_constr_avg')]) for x in max_samplers)


Out[519]:
{(0.25, 0.5, 0), (0.25, 1.0, 0), (0.25, 1.0, 2)}

In [520]:
set((x[constr_idx], x[excl_idx], x[sidx('n_sup_constr_avg')]) for x in max_samplers)


Out[520]:
{(0.25, 0.5, 3), (0.25, 1.0, 1), (0.25, 1.0, 3)}

In [521]:
odd = [x for x in min_samplers if x[constr_idx] == 0.25 and x[excl_idx] > 0]
len(odd)
print(samplers.description._v_names)


['pref_coeff_dist', 'pref_coeff_lb', 'pref_coeff_ub', 'assem_multi_commod_cutoff', 'assem_multi_commod_dist', 'n_commods_avg', 'n_commods_dist', 'sup_multi_cutoff', 'sup_multi_dist', 'n_supply_avg', 'n_supply_dist', 'sup_multi_commods_avg', 'sup_multi_commods_dist', 'exclusive_cutoff', 'exclusive_dist', 'sup_constr_val_cutoff', 'sup_constr_val_fracs', 'sup_constr_val_rand', 'n_sup_constr_avg', 'n_sup_constr_dist', 'n_req_constr_avg', 'n_req_constr_dist', 'req_multi_commods_avg', 'req_multi_commods_dist', 'connection_cutoff', 'connection_dist', 'req_qty_avg', 'req_qty_dist', 'assem_per_req_avg', 'assem_per_req_dist', 'n_request_avg', 'n_request_dist', 'paramid', 'constr_coeff_dist', 'constr_coeff_lb', 'constr_coeff_ub']

In [522]:
noprint = ['pref_coeff_lb', 'pref_coeff_ub', 'constr_coeff_lb', 'constr_coeff_ub', 'paramid', 'req_qty_avg']
toprint = [n for n in samplers.description._v_names if n not in noprint and not n.endswith('_dist')]
toprint


Out[522]:
['assem_multi_commod_cutoff',
 'n_commods_avg',
 'sup_multi_cutoff',
 'n_supply_avg',
 'sup_multi_commods_avg',
 'exclusive_cutoff',
 'sup_constr_val_cutoff',
 'sup_constr_val_fracs',
 'sup_constr_val_rand',
 'n_sup_constr_avg',
 'n_req_constr_avg',
 'req_multi_commods_avg',
 'connection_cutoff',
 'assem_per_req_avg',
 'n_request_avg']

In [523]:
def print_sampler_info(s):
    tot = []
    for r in s:
        c = []
        for n in toprint:
            x = r[sidx(n)]
            if x not in noprint:
                if type(x) is str and len(x.split()) != 4:
                    continue
            c.append(x)
        tot.append(c)
    
    print(toprint)
    print(len(tot))
    for t in tot:
        print(t)

In [524]:
print_sampler_info(max_samplers)


['assem_multi_commod_cutoff', 'n_commods_avg', 'sup_multi_cutoff', 'n_supply_avg', 'sup_multi_commods_avg', 'exclusive_cutoff', 'sup_constr_val_cutoff', 'sup_constr_val_fracs', 'sup_constr_val_rand', 'n_sup_constr_avg', 'n_req_constr_avg', 'req_multi_commods_avg', 'connection_cutoff', 'assem_per_req_avg', 'n_request_avg']
45
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 0, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 0, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 1, 2, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 2, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 2, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 15, 2, 0.5, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 2, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 0, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 2, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 20]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 0, 3, 0.5, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 2, 3, 0.5, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 0, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 2, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 0.5, 3, 20]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 0.5, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 0.5, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 20]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 20]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 0, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 0, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 15, 2, 0.5, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 0.5, 3, 20]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 0.5, 3, 20]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 0.5, 1, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 0.5, 3, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 0.5, 3, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 20]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 20]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 50]

In [525]:
print_sampler_info(mid_samplers)


['assem_multi_commod_cutoff', 'n_commods_avg', 'sup_multi_cutoff', 'n_supply_avg', 'sup_multi_commods_avg', 'exclusive_cutoff', 'sup_constr_val_cutoff', 'sup_constr_val_fracs', 'sup_constr_val_rand', 'n_sup_constr_avg', 'n_req_constr_avg', 'req_multi_commods_avg', 'connection_cutoff', 'assem_per_req_avg', 'n_request_avg']
16
[-1.0, 5, -1.0, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 0, 3, 0.5, 3, 50]
[-1.0, 5, -1.0, 15, 2, 0.5, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 20]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 1, 50]
[-1.0, 5, -1.0, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 2, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 0, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 2, 3, 1.0, 1, 50]
[-1.0, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 2, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 2, 3, 0.5, 3, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 0, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 1, 2, 3, 1.0, 3, 50]
[-1.0, 5, 0.5, 15, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', True, 3, 2, 3, 0.5, 3, 50]
[0.5, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 0.5, 3, 50]
[0.5, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 1, 50]
[0.5, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 0, 3, 1.0, 3, 50]
[0.5, 5, 0.5, 10, 2, 1.0, 0.25, '[0.25, 0.5, 0.75, 1]', False, 3, 2, 3, 1.0, 3, 50]

In [526]:
def count_elems(lst, verbose=False):
    c = defaultdict(int)
    for x in lst:
        c[x] += 1
    if verbose:
        for k, v in c.items():
            print(k, v)
    return c

In [527]:
lst = [(x[constr_idx], x[excl_idx], x[sidx('assem_multi_commod_cutoff')], x[sidx('n_sup_constr_avg')]) for x in max_samplers]
c = count_elems(lst, verbose=True)


(0.25, 1.0, -1.0, 1) 10
(0.25, 1.0, -1.0, 3) 33
(0.25, 0.5, -1.0, 3) 2

In [528]:
lst = [(x[constr_idx], x[excl_idx], x[sidx('assem_multi_commod_cutoff')], x[sidx('n_sup_constr_avg')]) for x in mid_samplers]
c = count_elems(lst, verbose=True)


(0.25, 1.0, -1.0, 1) 5
(0.25, 1.0, -1.0, 3) 6
(0.25, 1.0, 0.5, 3) 4
(0.25, 0.5, -1.0, 3) 1

In [529]:
lst = [(x[constr_idx], x[excl_idx], x[sidx('assem_multi_commod_cutoff')], x[sidx('n_sup_constr_avg')]) for x in min_samplers]
c = count_elems(lst, verbose=True)


(1.0, 0.5, -1.0, 3) 128
(0.25, -1.0, -1.0, 1) 128
(1.0, 0.5, 0.5, 1) 128
(1.0, 1.0, 0.5, 3) 128
(1.0, 1.0, -1.0, 3) 128
(0.25, 1.0, -1.0, 3) 89
(0.25, -1.0, 0.5, 1) 128
(0.25, 1.0, 0.5, 3) 124
(0.25, 0.5, -1.0, 3) 125
(1.0, -1.0, 0.5, 3) 128
(0.25, -1.0, -1.0, 3) 128
(1.0, 0.5, -1.0, 1) 128
(1.0, 0.5, 0.5, 3) 128
(1.0, 1.0, 0.5, 1) 128
(0.25, 0.5, 0.5, 1) 128
(0.25, 1.0, -1.0, 1) 113
(1.0, -1.0, 0.5, 1) 128
(0.25, 0.5, -1.0, 1) 128
(1.0, -1.0, -1.0, 1) 128
(1.0, 1.0, -1.0, 1) 128
(0.25, -1.0, 0.5, 3) 128
(0.25, 1.0, 0.5, 1) 128
(0.25, 0.5, 0.5, 3) 128
(1.0, -1.0, -1.0, 3) 128

In [530]:
lst = [(x[constr_idx], x[excl_idx], x[sidx('assem_multi_commod_cutoff')], x[sidx('n_req_constr_avg')]) for x in mid_samplers]
c = count_elems(lst, verbose=True)


(0.25, 1.0, -1.0, 0) 4
(0.25, 1.0, -1.0, 2) 7
(0.25, 1.0, 0.5, 2) 2
(0.25, 1.0, 0.5, 0) 2
(0.25, 0.5, -1.0, 2) 1

In [545]:
times = defaultdict(list)
for x in results.iterrows():
    times[x['solver']].append((x['instid'], x['time']))

objectives = defaultdict(list)
for x in results.iterrows():
    objectives[x['solver']].append((x['instid'], x['objective']))

pref_flow = defaultdict(list)
for x in results.iterrows():
    pref_flow[x['solver']].append((x['instid'], x['pref_flow']))

sum_flow = defaultdict(float)
for x in flows.iterrows():
    sum_flow[x['solnid']] += x['flow']

solns = {x['solnid']: (x['instid'], x['solver']) for x in results.iterrows()}
total_flow = defaultdict(list)
for sid, flow in sum_flow.items():
    solver = solns[sid][1]
    iid = solns[sid][0]
    total_flow[solver].append((iid, flow))
    cbc_flows = {x[0]: x[1] for x in total_flow['cbc']}
cbc_obj = {x[0]: x[1] for x in objectives['cbc']}
cbc_times = {x[0]: x[1] for x in times['cbc']}

These next graphs look at the ratio of objective function value to total system flow to see if it correlates with solution times. For a solution that uses false arcs (i.e., one or more supply constraints are tight), I would expect a high ratio value. Points that have a low ratio value are colored red.


In [546]:
def plt_ratio(iids, lim=2):
    y = np.array([cbc_obj[i] / cbc_flows[i] for i in iids])
    x = np.array([cbc_times[i] for i in iids])
    c = np.array(['b'] * len(y))
    c[y < lim] = 'r'
    plt.xlabel('Solution Time (s)')
    plt.ylabel('Ratio of Objective to Total Flow')
    #plt.xlim(0, max(x))
    plt.scatter(x, y, c=c)

In [547]:
iids = [i for i in max_iids if cbc_obj[i] < 1e8]
plt_ratio(iids, lim=3)
plt.title('Max Time IIDs')


Out[547]:
<matplotlib.text.Text at 0x7f9b6876f750>

In [542]:
iids = [i for i in mid_iids if cbc_obj[i] < 1e7]
plt_ratio(iids, lim=3)
plt.title('Mid Time IIDs')


Out[542]:
<matplotlib.text.Text at 0x7f9b4899d850>

In [543]:
iids = [i for i in min_iids if cbc_obj[i] < 1e8]
plt_ratio(iids, lim=10)
plt.title('Min Time IIDs')


Out[543]:
<matplotlib.text.Text at 0x7f9b488de7d0>

In [544]:
def fix(i):
    if len(i) == 16:
        return i
    else:
        return i + '\0'
#[(tools.uuidhex(fix(i)), cbc_times[i]) for i in max_iids if cbc_times[i] > 1e4]

In [ ]: