# Is it possible to achieve this type of design?

**URL:** <https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738>\
**Category:** Help\
**Created:** [July 8, 2021, 9:21pm UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738 "2021-07-08T21:21:21Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![solub](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@solub](https://forum.graphviz.org/u/solub)\
**Post date:** [July 8, 2021, 9:21pm UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738/1 "2021-07-08T21:21:21Z")

</div>

Hi again,

I am trying to design a very specific type of graph with certain colors and shapes but I am unable to tell if this is achievable with Graphviz.

My goal is to draw a directed graph where each node:

- is composed of 3 smaller boxes aligned horizontally (`striped` `rectangle` or `record`, `rounded`)
- contains 3 `labels` accordingly
- is filled with a gradient
- **has a black square node located on top of the middle box**

Example (_all black boxes have been placed manually_) :

 ![testModel](https://global.discourse-cdn.com/graphviz/original/1X/eb60ad1c7399d701e17f49333a048d7c2f10247f.jpeg)

I have made it to the third requirement but I am struggling implementing the last one. How would you place square nodes (`rect`, `square`, `box`, etc) on top of the first set of nodes (colored rectangles) so as they perfectly fit the dimensions of the middle boxes they are covering ? Is that even possible with Graphviz ?

Example code (Python):

```auto
# Dictionary storing relations between nodes
d = {0: set([1, 2, 3]), 
     1: set([4, 5, 6]), 
     2: set([7, 8, 9, 10]), 
     3: set([0]), 
     4: set([]), 
     5: set([]), 
     6: set([]), 
     7: set([]), 
     8: set([0]), 
     9: set([]), 
     10: set([])} 

# List of node labels (3 labels per node)
P = [('S', 'M', 'S'),
     ('M', 'S', 'L'),
     ('M', 'S', 'S'),
     ('M', 'S', 'M'),
     ('S', 'L', 'L'),
     ('S', 'L', 'M'),
     ('S', 'L', 'X'),
     ('S', 'S', 'S'),
     ('S', 'S', 'M'),
     ('S', 'S', 'L'),
     ('S', 'S', 'X')]

# Dictionary storing the colors corresponding to each label
c = {'S':'olivedrab1', 
     'M':'mediumturquoise', 
     'L':'deepskyblue', 
     'X':'palevioletred1'}

# Create a "directed graph" with general node and edge attributes
G = Digraph(node_attr={'shape':'record',  
                       'style':'rounded, filled',
                       'color':'white', 
                       'height':'0.1',
                       'fontcolor':'white'},
           
            edge_attr={'color':'grey', 
                       'arrowhead':'vee'} 
           )
       
G.attr('graph', bgcolor='transparent')

# 1st pass: create all nodes (0 to 10)
for k in d:
    l1, l2, l3 = P[k]
    
    # set specific attribute to each node (label & colors)
    G.attr('node', label='{} | {} | {}'.format(l1, ' ', l2), fillcolor='{}:{}'.format(c[l1], c[l2]))
    G.node(str(k))

# 2nd pass: create edges between nodes
for k in d:
    l1, l2, l3 = P[k]
    for i in d[k]:
        if i in d:
            G.edge(str(k), str(i))

# Then, how to overlap black square nodes ?

```

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [July 9, 2021, 12:12am UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738/2 "2021-07-09T00:12:29Z")

</div>

```auto
digraph G {
 node [shape=plaintext]
 t [label=<
 <TABLE border="1" cellborder="1" cellspacing="0" cellpadding="0" style="rounded"> 
  <TR>
    <TD WIDTH="50" BGCOLOR="red:blue" ><FONT COLOR="white">00</FONT></TD>
    <TD WIDTH="50" BGCOLOR="black"><FONT COLOR="white">02</FONT></TD>
    <TD WIDTH="50" BGCOLOR="pink:green"><FONT COLOR="white">03</FONT></TD>    
  </TR>
</TABLE>>];
}

```

Giving:  
 ![doneWithHtml](https://global.discourse-cdn.com/graphviz/original/1X/f20297e6da047dc509b32b8c10dba974fe389545.png)

---

<div class="post-metadata">

**Author:** ![solub](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@solub](https://forum.graphviz.org/u/solub)\
**Post date:** [July 9, 2021, 10:12am UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738/3 "2021-07-09T10:12:39Z")

</div>

Hi, thank you for the pointer !

The problem with this approach is that:

- there is 1 gradient per cell instead of 1 filling all three at once
- gradients are filling the inner cells, not the larger node.
- the overall outline is not sharp/clear because of the overlapping of multiple cell borders (inner+outer)

Illustration:

![example](https://global.discourse-cdn.com/graphviz/original/1X/d0241b381bb80fccdfa075a7e0d6f57bc33f42c8.png)

_When removing the inner cells’ borders for a cleaner outline, it becomes apparent that the gradients are not filling the main node._

Instead, is there a way to place a `rect` on top of the middle cell of a `record` node, just like in my previous example picture ?

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [July 10, 2021, 9:36pm UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738/4 "2021-07-10T21:36:54Z")

</div>

Very fiddly, but seemingly what you want.

- Start with dot to position the nodes
- Output to dot output format (dot -Tdot) (see [DOT | Graphviz](https://graphviz.org/docs/outputs/canon/))
- Use post-processing to add center node (see script below),
- Finally run through **neato -n** ([FAQ | Graphviz](https://graphviz.org/faq/#FaqDotWithNodeCoords))  
Demo graph:

```auto
digraph G {
 node [shape=Mrecord fontcolor="white"]
 triple [style=filled fillcolor="red:blue" label="<f0>AA|<f1>BB|<f2>CC"];
}

```

I used **gvpr** to add the center node overlay (see [https://graphviz.org/pdf/gvpr.1.pdf](https://graphviz.org/pdf/gvpr.1.pdf)), but seemingly **python** (or others) could be used

My script:

```auto
f=gradientOverlay.gv;
T=dot;
F=`basename $f .gv`;
/usr/bin/dot -T$T $f |
/usr/bin/gvpr -c 'BEGIN{int Z=0;node_t aNode}N{Z++;aNode=node($G,"__top_" + (string)Z);aNode.width=.05+(float)$.width/3.;aNode.height=$.height;aNode.pos=$.pos;aNode.shape="rect";aNode.style="filled";aNode.fillcolor="black";aNode.label=html($G,"<u>4&#960;</u><BR/>8");}'
|/usr/bin/neato -n -Tpng >O.png

```

Giving:  
 ![O](https://global.discourse-cdn.com/graphviz/original/1X/df30b7ba641b276ff2ee4c1857a16ad3349f9813.png)

The post-processing creates new, overlay nodes, using the **pos** of the original node. It sets attributes of the new node as needed, setting width to ~original width/3 and height to ~original height.

---

<div class="post-metadata">

**Author:** ![solub](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@solub](https://forum.graphviz.org/u/solub)\
**Post date:** [July 12, 2021, 10:57am UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738/5 "2021-07-12T10:57:13Z")

</div>

Thank you so much! I’ll see if I can implement this in Python.

---

<div class="post-metadata">

**Author:** ![solub](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@solub](https://forum.graphviz.org/u/solub)\
**Post date:** [July 12, 2021, 5:07pm UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738/6 "2021-07-12T17:07:53Z")

</div>

I am having a difficult time finding a way to do the same with Python. Am I correct that [gv.3python](https://www.graphviz.org/pdf/gv.3python.pdf) is the right extension to load in this case ? If so, where can I find it ?

If not, would you mind sharing a transcription of your example in Graphviz Python ? That would be very helpful.

---

<div class="post-metadata">

**Author:** ![steveroush](https://avatars.discourse-cdn.com/v4/letter/s/a9adbd/32.png) [@steveroush](https://forum.graphviz.org/u/steveroush)\
**Post date:** [July 14, 2021, 9:17pm UTC](https://forum.graphviz.org/t/is-it-possible-to-achieve-this-type-of-design/738/7 "2021-07-14T21:17:41Z")

</div>

[Note: _I am not a Python coder and have never used the PyGraphviz interface. Take my suggestions with a ton of salt_]

My best guess:

- I don’t think you need to worry about [gv.3python](https://www.graphviz.org/pdf/gv.3python.pdf)

1. Add the labels for the “overlay” nodes to the existing nodes using a new, made-up attribute name. I suggest something like **centerLabel**. It is completely legal to add new attribute name/value pairs to Graphviz files. Graphviz produces no error messages, but just passes them downstream.  
[after the code presented above]
2. G.layout to add positions to the graph
3. iterate through all the nodes. For each node with a **centerLabel** attribute (see above):  
3.1. use **node** command to create the overlay node (using a new, unique node name)  
3.2 set the overlay node **pos** equal to the old node **pos**  
3.3 set the overlay node **shape** to “rect”  
3.4 set the overlay node **style** to “filled”  
3.5 set the overlay node **fillcolor** to “black”  
3.6 set the overlay node **height** to ~ old node height - .02  
3.7 set the overlay node **width** to ~ .05 + (old node width/3)  
3.8 set the overlay node label to the old node **centerLabel** value
4. G.layout (again) but using the **neato** engine and **-n** arg
5. G.draw - I assume this produces the output

This is “best guess”. I hope it helps in some way.
