I am trying to configure my Digraph call so that each node uses the largest width and height required. Given the image below, each node would be the width of the first node and the height of the second. I have looked at the fixedsize attribute but it doesn't seem to be a fit. If fixedsize is set to true, the limits must be specified. If possible, I would rather have this automatically determined. The maximum required will depend on the node labels of a given graph and won't always be the same.
Sample setup:
dot = Digraph(comment="Example 1",
format='png',
edge_attr={'color':'black',
'style':'filled'},
graph_attr={'fixedsize':'false',
'bgcolor':'transparent'},
node_attr={'fontname':'bold',
'fontsize':'11',
'shape':'sqaure',
'color':'black',
'style':'filled',
'fillcolor':'lightsteelblue3'})
fixedsize: If false, the size of a node is determined by smallest width and height needed to contain its label and image, if any, with a margin specified by the margin attribute. The width and height must also be at least as large as the sizes specified by the width and height attributes, which specify the minimum values for these parameters. If true, the node size is specified by the values of the width and height attributes only and is not expanded to contain the text label. There will be a warning if the label (with margin) cannot fit within these limits. If the fixedsize attribute is set to shape, the width and height attributes also determine the size of the node shape, but the label can be much larger. Both the label and shape sizes are used when avoiding node overlap, but all edges to the node ignore the label and only contact the node shape. No warning is given if the label is too large.
Edit: A messy example, but an example none the less. I built the graph in 'gv' format, processed heights and widths, and rebuilt the graph.
from graphviz import Digraph
dot = Digraph(comment="Example 1",
format='gv',
edge_attr={'color':'brown',
'style':'filled'},
graph_attr={'rankdir':'LR',
'bgcolor':'transparent'},
node_attr={'fontsize':'11',
'shape':'sqaure',
'color':'black',
'style':'filled',
'fillcolor':'antiquewhite'})
# nodes and edges
dot.node('1', 'This is the longest width')
dot.node('2', 'This\nis\nthe\nlargest\nheight')
dot.node('3', 'Small')
dot.edges(['12','23'])
def get_node_max(digraph):
import re
heights = [height.split('=')[1] for height in re.findall('height=[0-9.]+', str(digraph))]
widths = [width.split('=')[1] for width in re.findall('width=[0-9.]+', str(digraph))]
heights.sort(key=float)
widths.sort(key=float)
return heights[len(heights)-1], widths[len(widths)-1]
params = {'format':'png', 'fixedsize':'false', 'width':'1', 'height':'1'}
params['height'], params['width'] = get_node_max(dot.pipe())
dot = Digraph(comment="Example 1",
format=params['format'],
edge_attr={'color':'brown',
'style':'filled'},
graph_attr={'rankdir':'LR',
'bgcolor':'transparent'},
node_attr={'fixedsize':params['fixedsize'],
'width':params['width'],
'height':params['height'],
'fontsize':'11',
'shape':'sqaure',
'color':'black',
'style':'filled',
'fillcolor':'antiquewhite'})
# nodes and edges
dot.node('1', 'This is the longest width')
dot.node('2', 'This\nis\nthe\nlargest\nheight')
dot.node('3', 'Small')
dot.edges(['12','23'])
dot.render('example-graphviz.gv', view=True)
You can add explicit fixed width
and height
node-attributes, e.g.
node_attr={'fixedsize': 'true',
'width': '2',
'height': '1.5',
...}
This forces all nodes to have the same size.
Of course, you have to manually determine the "right" values for width
and height
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With