In [16]:
import networkx as nx
from networkx.utils import open_file, make_str

In [2]:
%matplotlib inline

In [3]:
file = '/Users/mark/seriationct/experiments/seriationct-7/seriation-results/a7eb7f58-d34e-11e4-93bf-b8f6b1154c9b-0-sampled-0.1/a7eb7f58-d34e-11e4-93bf-b8f6b1154c9b-0-sampled-0.1-minmax-by-weight.png-annotated.gml'

In [114]:
g = nx.read_gml(file)

In [28]:
nx.draw(g, pos=nx.spring_layout(g))



In [85]:
def write_ordered_dot(N,path,name=None):
    """Write NetworkX graph G to Graphviz dot format on path.

    Path can be a string or a file handle.
    """
    try:
        import pydot
    except ImportError:
        raise ImportError("write_dot() requires pydot",
                          "http://code.google.com/p/pydot/")
    P=generate_ordered_dot(N, name)

    title_string = "\nlabelloc=\'t\';label=\'%s\';}\n" % name

    p = P.to_string();
    # p2 = re.sub("\n\}\n", "", p)
    # p2 += "\nlabelloc=\"t\";\n"
    # p2 += "label=\"%s\";\n}\n" % name
    
    with open(path, 'wb') as pathfile:
        pathfile.write(p)
    return




def generate_ordered_dot(N, name=None):
    """
    The networkx write_dot() function generates
    """
    try:
        import pydot
    except ImportError:
        raise ImportError('to_pydot() requires pydot: '
                          'http://code.google.com/p/pydot/')

    # set Graphviz graph type
    if N.is_directed():
        graph_type='digraph'
    else:
        graph_type='graph'
    strict=N.number_of_selfloops()==0 and not N.is_multigraph()

    node_attrs = dict()
    node_attrs["shape"] = "circle"
    node_attrs["width"] = "0.3"
    node_attrs["height"] = "0.3"
    node_attrs["label"] = ""
    #node_attrs["fixedsize"] = "true"
    node_attrs["style"] = "filled"

    graph_defaults=N.graph.get('graph',{})
    graph_defaults["ratio"] = "auto"
    graph_defaults["labelloc"] = "b"
    graph_defaults["label"] = name
    graph_defaults["pad"] = "1.0"


    if name is None:
        P = pydot.Dot(graph_type=graph_type,strict=strict,**graph_defaults)
    else:
        P = pydot.Dot('"%s"'%name,graph_type=graph_type,strict=strict,
                      **graph_defaults)
    try:
        P.set_node_defaults(**node_attrs)
    except KeyError:
        pass
    try:
        P.set_edge_defaults(**N.graph['edge'])
    except KeyError:
        pass

    for n,nodedata in sorted(N.nodes_iter(data=True), key=lambda n: int(n[0])):
        str_nodedata=dict((k,make_str(v)) for k,v in nodedata.items())
        
        if "name" in str_nodedata:
            del str_nodedata['name']
        
        print "str_nodedata: %s" % str_nodedata
        p=pydot.Node(make_str(n),**str_nodedata)
        P.add_node(p)

    if N.is_multigraph():
        for u,v,key,edgedata in N.edges_iter(data=True,keys=True):
            str_edgedata=dict((k,make_str(v)) for k,v in edgedata.items())
            edge=pydot.Edge(make_str(u),make_str(v),key=make_str(key),**str_edgedata)
            P.add_edge(edge)

    else:



        for u,v,edgedata in sorted(N.edges_iter(data=True), key=lambda u: int(u[0]) ):
            str_edgedata=dict((k,make_str(v)) for k,v in edgedata.items())
            if int(v) < int(u):
                edge = pydot.Edge(make_str(v),make_str(u),**str_edgedata)
            else:
                edge=pydot.Edge(make_str(u),make_str(v),**str_edgedata)
            P.add_edge(edge)
    return P

In [24]:
write_ordered_dot(g, "/Users/mark/tmp/test.dot")


str_nodedata: {'xCoordinate': u'49.0', 'appears_in_slice': u'15', 'yCoordinate': u'31.0', 'level': u'child', 'label': u'assemblage-31-49', 'child_of': u'assemblage-34-37', 'parent_node': u'assemblage-34-37', 'id': u'0', 'size': u'312.263661735'}
str_nodedata: {'xCoordinate': u'34.0', 'appears_in_slice': u'12', 'yCoordinate': u'6.0', 'level': u'grandchild', 'label': u'assemblage-6-34', 'child_of': u'assemblage-23-47', 'parent_node': u'assemblage-60-3', 'id': u'1', 'size': u'342.678102186'}
str_nodedata: {'xCoordinate': u'14.0', 'appears_in_slice': u'15', 'yCoordinate': u'22.0', 'level': u'grandchild', 'label': u'assemblage-22-14', 'child_of': u'assemblage-64-39', 'parent_node': u'assemblage-45-49', 'id': u'2', 'size': u'312.263661735'}
str_nodedata: {'xCoordinate': u'68.0', 'appears_in_slice': u'15', 'yCoordinate': u'34.0', 'level': u'grandchild', 'label': u'assemblage-34-68', 'child_of': u'assemblage-23-55', 'parent_node': u'assemblage-28-29', 'id': u'3', 'size': u'312.263661735'}
str_nodedata: {'xCoordinate': u'41.0', 'appears_in_slice': u'4', 'yCoordinate': u'30.0', 'level': u'grandchild', 'label': u'assemblage-30-41', 'child_of': u'assemblage-23-55', 'parent_node': u'assemblage-63-56', 'id': u'4', 'size': u'619.755402642'}
str_nodedata: {'xCoordinate': u'19.0', 'appears_in_slice': u'3', 'yCoordinate': u'8.0', 'level': u'child', 'label': u'assemblage-8-19', 'child_of': u'assemblage-57-46', 'parent_node': u'assemblage-57-46', 'id': u'5', 'size': u'668.278670854'}
str_nodedata: {'xCoordinate': u'70.0', 'appears_in_slice': u'7', 'yCoordinate': u'53.0', 'level': u'grandchild', 'label': u'assemblage-53-70', 'child_of': u'assemblage-64-39', 'parent_node': u'assemblage-68-63', 'id': u'6', 'size': u'1482.31068176'}
str_nodedata: {'xCoordinate': u'55.0', 'appears_in_slice': u'8', 'yCoordinate': u'66.0', 'level': u'grandchild', 'label': u'assemblage-66-55', 'child_of': u'assemblage-64-39', 'parent_node': u'assemblage-60-48', 'id': u'7', 'size': u'255.909549086'}
str_nodedata: {'xCoordinate': u'63.0', 'appears_in_slice': u'7', 'yCoordinate': u'70.0', 'level': u'grandchild', 'label': u'assemblage-70-63', 'child_of': u'assemblage-64-39', 'parent_node': u'assemblage-68-63', 'id': u'8', 'size': u'280.791707695'}
str_nodedata: {'xCoordinate': u'12.0', 'appears_in_slice': u'4', 'yCoordinate': u'35.0', 'level': u'grandchild', 'label': u'assemblage-35-12', 'child_of': u'assemblage-23-47', 'parent_node': u'assemblage-34-7', 'id': u'9', 'size': u'283.247586364'}
str_nodedata: {'xCoordinate': u'17.0', 'appears_in_slice': u'6', 'yCoordinate': u'62.0', 'level': u'grandchild', 'label': u'assemblage-62-17', 'child_of': u'assemblage-23-55', 'parent_node': u'assemblage-38-25', 'id': u'10', 'size': u'312.324840208'}
str_nodedata: {'xCoordinate': u'22.0', 'appears_in_slice': u'3', 'yCoordinate': u'50.0', 'level': u'grandchild', 'label': u'assemblage-50-22', 'child_of': u'assemblage-64-39', 'parent_node': u'assemblage-68-51', 'id': u'11', 'size': u'385.03108449'}
str_nodedata: {'xCoordinate': u'58.0', 'appears_in_slice': u'4', 'yCoordinate': u'65.0', 'level': u'child', 'label': u'assemblage-65-58', 'child_of': u'assemblage-58-16', 'parent_node': u'assemblage-58-16', 'id': u'12', 'size': u'932.080242849'}
str_nodedata: {'xCoordinate': u'27.0', 'appears_in_slice': u'6', 'yCoordinate': u'36.0', 'level': u'child', 'label': u'assemblage-36-27', 'child_of': u'assemblage-10-43', 'parent_node': u'assemblage-10-43', 'id': u'13', 'size': u'593.116547903'}
str_nodedata: {'xCoordinate': u'33.0', 'appears_in_slice': u'2', 'yCoordinate': u'52.0', 'level': u'child', 'label': u'assemblage-52-33', 'child_of': u'assemblage-57-46', 'parent_node': u'assemblage-57-46', 'id': u'14', 'size': u'407.684598757'}

In [123]:
def build_colormap_for_nodes(input_graph, scheme):
    """
    Iterates over the nodes in a graph, looking for 'level' attributes.  For 
    each child, picks a color and caches it, and a color for the root.  Then, assigns
    grandchildren the color of their 'child_of' attribute.  Adds the 'color' attribute
    to each node in the NetworkX graph, and then returns the graph.
    """
    
    # make a copy so we don't touch the original graph, we'll return a new one
    g = input_graph.copy()
    
    color_cache = dict()
    color_list = range(1, 11) # rdylgn11 brewer scheme in graphviz
    root_color = color_list.pop()
    
    # figure out penwidth scaling
    slice_ids = []
    for node, data in g.nodes_iter(data=True):
        slice_ids.append(g.node[node]['appears_in_slice'])
    
    max_slice = max(slice_ids)
    max_penwidth = 5.0
    
    
    
    
    # grandchildren might point their child_of attribute at a node which is not present
    # in this minmax graph given that we're operating with a sample of assemblages.  
    # So when we find a child_of that's not represented in the 
    for node, data in g.nodes_iter(data=True):
        
        lab = g.node[node]['label']
        short_label = lab.replace('assemblage-','')
        #del g.node[node]['label']
        g.node[node]['short_label']= short_label
        
        g.node[node]['colorscheme'] = scheme
        g.node[node]['penwidth'] = (float(g.node[node]['appears_in_slice']) / max_slice) * max_penwidth
        
        if g.node[node]['level'] == 'root':
            g.node[node]['fillcolor'] = root_color
            color_cache[node] = root_color
            g.node[node]['shape'] = 'square'
        elif g.node[node]['level'] == 'child':
            name = g.node[node]['label']
            g.node[node]['shape'] = 'diamond'
            if name not in color_cache:
                color = color_list.pop()
                g.node[node]['fillcolor'] = color
                color_cache[name] = color
            else:
                color = color_cache[name]
                g.node[node]['fillcolor'] = color
        elif g.node[node]['level'] == 'grandchild':
            parent = g.node[node]['child_of']
            g.node[node]['shape'] = 'circle'
            if parent not in color_cache:
                color = color_list.pop()
                color_cache[parent] = color
                g.node[node]['fillcolor'] = color
            else:
                color = color_cache[parent]
                g.node[node]['fillcolor'] = color

    for node, data in g.nodes_iter(data=True):
        g.node[node]['label'] = g.node[node]['short_label']
                
            
    #print "color_cache: %s" % color_cache
    
            
    return g

In [124]:
gcolor = build_colormap_for_nodes(g, 'rdylgn11')

In [125]:
write_ordered_dot(gcolor, "/Users/mark/tmp/test.dot")


str_nodedata: {'xCoordinate': u'49.0', 'appears_in_slice': u'15', 'yCoordinate': u'31.0', 'colorscheme': u'rdylgn11', 'level': u'child', 'child_of': u'assemblage-34-37', 'short_label': u'31-49', 'label': u'31-49', 'shape': u'diamond', 'fillcolor': u'9', 'size': u'312.263661735', 'parent_node': u'assemblage-34-37', 'id': u'0', 'penwidth': u'5.0'}
str_nodedata: {'xCoordinate': u'34.0', 'appears_in_slice': u'12', 'yCoordinate': u'6.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-23-47', 'short_label': u'6-34', 'label': u'6-34', 'shape': u'circle', 'fillcolor': u'8', 'size': u'342.678102186', 'parent_node': u'assemblage-60-3', 'id': u'1', 'penwidth': u'4.0'}
str_nodedata: {'xCoordinate': u'14.0', 'appears_in_slice': u'15', 'yCoordinate': u'22.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-64-39', 'short_label': u'22-14', 'label': u'22-14', 'shape': u'circle', 'fillcolor': u'7', 'size': u'312.263661735', 'parent_node': u'assemblage-45-49', 'id': u'2', 'penwidth': u'5.0'}
str_nodedata: {'xCoordinate': u'68.0', 'appears_in_slice': u'15', 'yCoordinate': u'34.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-23-55', 'short_label': u'34-68', 'label': u'34-68', 'shape': u'circle', 'fillcolor': u'6', 'size': u'312.263661735', 'parent_node': u'assemblage-28-29', 'id': u'3', 'penwidth': u'5.0'}
str_nodedata: {'xCoordinate': u'41.0', 'appears_in_slice': u'4', 'yCoordinate': u'30.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-23-55', 'short_label': u'30-41', 'label': u'30-41', 'shape': u'circle', 'fillcolor': u'6', 'size': u'619.755402642', 'parent_node': u'assemblage-63-56', 'id': u'4', 'penwidth': u'1.33333333333'}
str_nodedata: {'xCoordinate': u'19.0', 'appears_in_slice': u'3', 'yCoordinate': u'8.0', 'colorscheme': u'rdylgn11', 'level': u'child', 'child_of': u'assemblage-57-46', 'short_label': u'8-19', 'label': u'8-19', 'shape': u'diamond', 'fillcolor': u'5', 'size': u'668.278670854', 'parent_node': u'assemblage-57-46', 'id': u'5', 'penwidth': u'1.0'}
str_nodedata: {'xCoordinate': u'70.0', 'appears_in_slice': u'7', 'yCoordinate': u'53.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-64-39', 'short_label': u'53-70', 'label': u'53-70', 'shape': u'circle', 'fillcolor': u'7', 'size': u'1482.31068176', 'parent_node': u'assemblage-68-63', 'id': u'6', 'penwidth': u'2.33333333333'}
str_nodedata: {'xCoordinate': u'55.0', 'appears_in_slice': u'8', 'yCoordinate': u'66.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-64-39', 'short_label': u'66-55', 'label': u'66-55', 'shape': u'circle', 'fillcolor': u'7', 'size': u'255.909549086', 'parent_node': u'assemblage-60-48', 'id': u'7', 'penwidth': u'2.66666666667'}
str_nodedata: {'xCoordinate': u'63.0', 'appears_in_slice': u'7', 'yCoordinate': u'70.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-64-39', 'short_label': u'70-63', 'label': u'70-63', 'shape': u'circle', 'fillcolor': u'7', 'size': u'280.791707695', 'parent_node': u'assemblage-68-63', 'id': u'8', 'penwidth': u'2.33333333333'}
str_nodedata: {'xCoordinate': u'12.0', 'appears_in_slice': u'4', 'yCoordinate': u'35.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-23-47', 'short_label': u'35-12', 'label': u'35-12', 'shape': u'circle', 'fillcolor': u'8', 'size': u'283.247586364', 'parent_node': u'assemblage-34-7', 'id': u'9', 'penwidth': u'1.33333333333'}
str_nodedata: {'xCoordinate': u'17.0', 'appears_in_slice': u'6', 'yCoordinate': u'62.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-23-55', 'short_label': u'62-17', 'label': u'62-17', 'shape': u'circle', 'fillcolor': u'6', 'size': u'312.324840208', 'parent_node': u'assemblage-38-25', 'id': u'10', 'penwidth': u'2.0'}
str_nodedata: {'xCoordinate': u'22.0', 'appears_in_slice': u'3', 'yCoordinate': u'50.0', 'colorscheme': u'rdylgn11', 'level': u'grandchild', 'child_of': u'assemblage-64-39', 'short_label': u'50-22', 'label': u'50-22', 'shape': u'circle', 'fillcolor': u'7', 'size': u'385.03108449', 'parent_node': u'assemblage-68-51', 'id': u'11', 'penwidth': u'1.0'}
str_nodedata: {'xCoordinate': u'58.0', 'appears_in_slice': u'4', 'yCoordinate': u'65.0', 'colorscheme': u'rdylgn11', 'level': u'child', 'child_of': u'assemblage-58-16', 'short_label': u'65-58', 'label': u'65-58', 'shape': u'diamond', 'fillcolor': u'4', 'size': u'932.080242849', 'parent_node': u'assemblage-58-16', 'id': u'12', 'penwidth': u'1.33333333333'}
str_nodedata: {'xCoordinate': u'27.0', 'appears_in_slice': u'6', 'yCoordinate': u'36.0', 'colorscheme': u'rdylgn11', 'level': u'child', 'child_of': u'assemblage-10-43', 'short_label': u'36-27', 'label': u'36-27', 'shape': u'diamond', 'fillcolor': u'3', 'size': u'593.116547903', 'parent_node': u'assemblage-10-43', 'id': u'13', 'penwidth': u'2.0'}
str_nodedata: {'xCoordinate': u'33.0', 'appears_in_slice': u'2', 'yCoordinate': u'52.0', 'colorscheme': u'rdylgn11', 'level': u'child', 'child_of': u'assemblage-57-46', 'short_label': u'52-33', 'label': u'52-33', 'shape': u'diamond', 'fillcolor': u'2', 'size': u'407.684598757', 'parent_node': u'assemblage-57-46', 'id': u'14', 'penwidth': u'0.666666666667'}

In [ ]: