def addGraphPretty(model, ax, \
                   positions = None, \
                   cmap = cm.tab20, **kwargs):

    from matplotlib.patches import FancyArrowPatch, Circle, ConnectionStyle, Wedge
    r = .115  # radius for circle
    graph = model.graph

    if positions is None:
        positions = nx.circular_layout(graph)
# colors  = cm.tab20(arange(model.nNodes))
# colors  = cm.get_cmap('tab20')(arange(model.nNodes))
    if graph.number_of_nodes() > 20:
        cmap = cm.get_cmap('gist_rainbow')

    colors = cmap(arange(model.nNodes))

    # DEFAULTS
    circlekwargs = dict(\
                             radius    = r, \
                             alpha     = 1, \
                             edgecolor = 'black', \
                             linewidth = 1, \
                             linestyle = 'solid',\
                             zorder    = 2)
    for k, v in kwargs.get('circle', {}).items():
        circlekwargs[k] = v

    annotatekwargs = dict(\
                          horizontalalignment = 'center', \
                          verticalalignment = 'center', \
                          transform = ax.transAxes, \
                          fontsize = 12,\
                          )

    for k, v in kwargs.get('annotate', {}).items():
        annotatekwargs[k] = v

    for n in graph:
        # make circle
        c = Circle(positions[n], facecolor = colors[model.mapping[n]],\
                   **circlekwargs)
        # add label
        # print(c.center[:2], pos[n])
        # ax.text(*c.center, n, horizontalalignment = 'center', \
        # verticalalignment = 'center', transform = ax.transAxes)
        annotatekwargs['fontsize'] = .95 * circlekwargs['radius']
        ax.annotate(n, c.center, **annotatekwargs)
        # add to ax
        ax.add_patch(c)
        # TODO : remove tis for member assignment

        # bookkeep for adding edge
        graph.node[n]['patch'] = c

    seen = {}  # bookkeeping
    from copy import copy
    # arrow style for drawing
    arrowsprops = dict(\
                   arrowstyle = '-|>' if graph.is_directed() else '<|-|>' ,\
                   mutation_scale = 15.0,\
                   lw = 2,\
                   alpha = 1,\
                   )

    edgesScaling = {(u, v): graph[u][v]['weight'] for u, v in graph.edges()}
    minWeight, maxWeight = min(edgesScaling.values()), max(
        edgesScaling.values())

    for u, v in graph.edges():
        n1 = graph.node[u]['patch']
        n2 = graph.node[v]['patch']
        d = graph[u][v]['weight']
        rad = 0.1
        if (u, v) in seen:
            rad = seen.get((u, v))
            rad = (rad + np.sign(rad) * 0.1) * -1

        # set properties of the edge
        alphaEdge = clip(abs(d), .2, 1)
        arrowsprops['color'] = 'green' if d > 0 else 'red'
        #        arrowsprops['alpha'] = alphaEdge
        arrowsprops['lw'] = ((d - minWeight) / (maxWeight - minWeight)) * 5

        # self-edge is a special case
        if u == v:
            n2 = copy(n1)
            n1 = copy(n1)
            theta = random.uniform(0, 2 * pi)

            rotation = pi
            corner1 = array([sin(theta), cos(theta)]) * r
            corner2   = array([sin(theta + rotation), cos(theta + rotation)]) *\
            r + .12 * sign(random.randn()) * r

            n1.center = array(n1.center) + corner1
            n2.center = array(n2.center) + corner2

            #            n1.center = (n1.center[0] + r, n1.center[1] )
            #            n2.center = (n2.center[0] - r, n2.center[1])
            rad = radians(135)  # trial and error

            # add edge
            e = FancyArrowPatch(n2.center, n1.center, **arrowsprops)
            e.set_arrowstyle(head_length=head_length)
        else:
            e  = FancyArrowPatch(n1.center,n2.center, patchA = n1, patchB = n2,\
                                connectionstyle = f'arc3,rad={rad}',
                                **arrowsprops)

        seen[(u, v)] = rad
        ax.add_patch(e)
    ax.autoscale()
    ax.set_aspect('equal')
    return ax
def showGraph(graph, attr='weight'):
    '''
    Shows the adjacency matrix and the 'graphical layout'
    '''
    # TODO: add curved arreas
    # TODO: plot add zeros
    # ugly af
    #    style.use('seaborn-white')
    fig, axes = subplots(1, 2)
    u = unique(list(nx.get_edge_attributes(graph, attr).values()))
    cmap = cm.get_cmap('viridis')
    #    cmap = cm.get_cmap('viridis')(linspace(-1, 1, 20))
    #    cmap[0,:] = 0
    #    cmap.set_over('DarkViolet')
    # adjacency plot
    adj = nx.adjacency_matrix(graph, weight='weight').todense()

    #    adj = (adj - adj.min()) / (adj.max() - adj.min())
    #    adj[adj == 0] = nan
    cmap.set_bad('gray', .2)

    h = axes[0].imshow(\
            adj, aspect = 'auto',\
            cmap = cmap,\
            )

    cbar = colorbar(h, ax=axes[0], pad=.01)
    text(1.15, .5 , 'weight', rotation = 90,\
         horizontalalignment='center', \
         fontsize           = 20,\
         transform          = axes[0].transAxes)

    cbar.set_ticks([round(min(u), 2), round(max(u), 2)])
    x = arange(len(graph.nodes()))
    axes[0].set_xticks(x)
    axes[0].set_xticklabels(graph.nodes(), ha='center', va='top', minor=False)
    axes[0].set_yticks(x)
    axes[0].set_yticklabels(graph.nodes(), ha='center', minor=False)
    axes[0].tick_params(axis='y', which='major', pad=35)
    #    cbar.set_ticklabels([])
    setp(axes[0], **dict(xlabel='node', ylabel='node'))
    fig.autofmt_xdate()  # slant overlapping labels
    # there probably is a wrapper keyword for this....

    from matplotlib.patches import FancyArrowPatch, Circle, ConnectionStyle
    # graphical layout

    edges = nx.get_edge_attributes(graph, 'weight')
    negatives = {}
    positives = {}
    maxWeight = max(list(edges.values()))
    for key, value in edges.items():
        value = round(value, 3)
        edges[key] = value
        if value < 0:
            negatives[key] = value
        else:
            positives[key] = value

    r = 2
    pos = nx.circular_layout(graph, scale=20)
    for n in graph:
        c=Circle(positions[n], radius=r,alpha=1, facecolor = 'white',\
                 edgecolor = 'black', linewidth  = 1, linestyle = 'solid')
        text(*c.center,
             n,
             horizontalalignment='center',
             verticalalignment='center')
        axes[1].add_patch(c)
        graph.node[n]['patch'] = c
        x, y = positions[n]
#    pos = nx.circular_layout(graph, scale = .5)
#    tmp = nx.get_edge_attributes(graph, 'weight')
#    tmp = {key: abs(value) for key, value in tmp.items()}
#    nx.set_edge_attributes(graph, tmp, 'absweight')
#    pos = nx.kamada_kawai_layout(graph, weight=  'absweight', scale= 100000)
#    patches = nx.draw_networkx_nodes(graph, pos = pos, alpha = 1, node_size = 1500, edgecolors = 'black', node_color = 'white')
    seen = {}
    from copy import copy
    for u, v in graph.edges():
        n1 = graph.node[u]['patch']
        n2 = graph.node[v]['patch']
        d = graph[u][v]['weight']
        rad = 0.1
        if (u, v) in seen:
            rad = seen.get((u, v))
            rad = (rad + np.sign(rad) * 0.1) * -1
            print(u, v)
        if u == v:
            j = .1
            n2 = copy(n1)
            n1 = copy(n1)
            n1.center = (n1.center[0] + r, n1.center[1])
            n2.center = (n2.center[0] - r, n2.center[1])
            #            n1.center = tuple(i - j for i in n1.center)
            #            n2.center = tuple(i + j for i in n2.center)
            print(n1, n2)
            rad = 1.6
            print(n1.center, n2.center)
            e = FancyArrowPatch(n2.center, n1.center, connectionstyle = f'arc3,rad={rad}',\
                                arrowstyle = '-|>',\
                                mutation_scale = 10.0,
                                lw = 2,
                                alpha = abs(d),
                                color = 'red' if d < 0 else 'green')
            e.set_arrowstyle(arrowstyle='-|>', head_length=1.5)
        else:
            connectionstyle = f'arc3,rad={rad}'
            e = FancyArrowPatch(n1.center,n2.center, patchA = n1, patchB = n2,\
                                arrowstyle = '->',
                                connectionstyle = connectionstyle,
                                mutation_scale = 10.0,
                                lw=2,
                                alpha=  abs(d),
                                color= 'red' if d < 0 else 'green')

#        if (u,v) not in seen:
#            center = (n1.center + n2.center) / 2 + random.rand()
#            text(*center, round(d,2))
        seen[(u, v)] = rad
        axes[1].add_patch(e)


#    nx.draw_networkx_labels(graph, pos = pos,\
#                                          node_labels = graph.nodes())
#
#    nx.draw_networkx_edges(graph,
#                           pos,
#                           edgelist = negatives,
#                           width =  list(negatives.values()), edge_color = 'red',
#                           edge_labels = negatives, ax = axes[-1])
#    nx.draw_networkx_edges(graph,
#                           pos,
#                           edgelist = positives,
#                           width = list(positives.values()), edge_color =  'green',
#                           edge_labels = positives, ax = axes[-1]
#                           )
#    nx.draw_networkx_edge_labels(graph, pos, edge_labels = edges, ax = axes[-1], label_pos  = .5)
    axes[-1].autoscale()
    axes[-1].axis('off')