Reputation:
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
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
Upvotes: 6
Views: 3472
Reputation: 1
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).
Upvotes: 0
Reputation: 6773
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
Upvotes: 0
Reputation: 183
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
}
>>>
Upvotes: 0
Reputation: 20620
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.
Upvotes: 4