6

I am getting acquainted with graphviz within Python 2.7. Is it possible to change the properties of a single node after it has been drawn?

e.g.

from graphviz import Digraph
q = Digraph()
q.node('a')
q.node('b')
q.edge('a','b')

q

Output of simple graph

Is it possible to change the color of node 'b' after the fact? I am aware that I can set it at the time of generation by

q.node('b', color = 'blue')

But, I'd like to be able to change it after generating it.

This link Color a particular node in Networkx and Graphviz

suggests using the graph's .node property to update a dict

G.node[2]['fillcolor']='red'

By analogy, I tried

q.node['b']['color'] = 'blue'

which gives an error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-54-43b05071d09a> in <module>()
----> 1 q.node['b']['color'] = 'blue'

TypeError: 'instancemethod' object has no attribute '__getitem__'

I think this may be because I am not using networkx as in the previous case.

I've also read the graphviz docs at http://graphviz.org/content/attrs but none of my experiments have worked. I'm sure it is something straightforward but I am missing it...

--- Old Guy In The Club

4 Answers4

4

I've read through the API docs and don't think it's possible to edit a node after construction.

If you don't want to use networkx, one workaround would be to store the graph in your own data structure and use that to create the graphviz graph at the point when you're ready to (re-)render it. For example, you could keep a list of the names of all the nodes that should be blue, and then refer to that at the point of constructing your graphviz graph. Separating the model from its rendering in this way might also lead to easier maintenance.

Matthew Strawbridge
  • 19,940
  • 10
  • 72
  • 93
  • I tried some experiments with networkx - it has some very nice features but a couple things I have in mind seem a little more complicated than pure graphviz. Your idea of having categories of nodes updated as a batch sounds like a good approach to what I ultimately would like to do. I'll try that route. Thanks for the prompt reply. –  Jun 03 '17 at 00:37
0

One way to do it is by editing the graph object directly.

>>> from graphviztest import *
>>> import json
>>> dot = Digraph(comment='My graph', format='png')
>>> dot.node('A', 'hurr')
>>> dot.node('B', 'durr')
>>> dot.edge('A','B')
>>> print dot
// My graph
digraph {
    A [label=hurr]
    B [label=durr]
    A -> B
}
>>> print json.dumps(dot.__dict__, indent=2)
{
  "comment": "My graph", 
  "_encoding": "utf-8", 
  "name": null, 
  "edge_attr": {}, 
  "_format": "png", 
  "body": [
    "\tA [label=hurr]", 
    "\tB [label=durr]", 
    "\tA -> B"
  ], 
  "filename": "Digraph.gv", 
  "graph_attr": {}, 
  "strict": false, 
  "node_attr": {}
}
>>> dot.body[0] = '\tA [label=derp]'
>>> dot.body[1] = '\tB [label=blah]'
>>> print dot
// My graph
digraph {
    A [label=derp]
    B [label=blah]
    A -> B
}
>>> 


PizzaBeer
  • 183
  • 14
0

You could also save the resulting graph in SVG and edit the SVG directly, changing the color of a given node using CSS. In SVG, generated nodes have ids, making it easy to change the color (stroke attribute).

Gaurav Shrivastava
  • 905
  • 12
  • 19
0

If you set your output format to dot, the layout is calculated, but not actually drawn. You can then modify that (augmented) Graphviz file with Python, sed, awk, or gvpr (https://www.graphviz.org/pdf/gvpr.1.pdf) to modify colors and/or other attributes.
Then use this command to draw the graph: neato -n2 -Tpng myfile.dot >myfile.png
See here for more info on delayed drawing: https://www.graphviz.org/faq/#FaqDotWithCoordsor

sroush
  • 5,375
  • 2
  • 5
  • 11