简体   繁体   中英

Graphviz/Python: Recoloring a single node after it has been generated

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?

eg

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

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.

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
}
>>> 


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).

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM