I'm creating some multilevel SEM graphs and I'm running into a small problem. The latent variable at the bottom of the graph (labeled "WF") is supposed to have a double-headed edge to and from it but the edge should go under the node. Note the correct orientation of the topmost node. Seems and easy fix but I can find it. Thanks in advance. (BTW, I've provided only a snippet of the original model, but this is sufficient for the purpose.)
digraph stackex {
{rank=min;
bf [shape=ellipse]
bf:nw -> bf:ne [dir = both]}
{node[shape=square]
bf -> i1
i1[label=X1]
i1 -> wf [dir=back]}
{wf [shape=ellipse]
wf:sw -> wf:se [dir = both]}
}
And here's what it produces:
The double-headed arrow should go under the node labled "WF".
Based on experimentation, it appears that the only way to get
wf:sw -> wf:se [dir = both]
to do what you want is to add
graph [rankdir=TB]
Unfortunately, rankdir affects the entire graph (not just a subgraph or cluster). So you can fix one loop, but you break the other.
The only way I've found to accomplish your goal is to hand-modify the pos of the offending edge (spline). This:
digraph stackex {
graph [bb="0,0,82.583,216"];
node [label="\N",
shape=square
];
bf [height=0.5,
pos="41.292,162",
shape=ellipse,
width=0.75];
bf:nw -> bf:ne [dir=both,
pos="s,26.292,177 e,56.292,177 22.277,186.17 18.135,200.16 21.792,216 41.292,216 60.792,216 64.448,200.16 60.306,186.17"];
i1 [height=0.5,
label=X1,
pos="41.292,90",
width=0.5];
bf -> i1 [pos="e,41.292,108.1 41.292,143.7 41.292,135.98 41.292,126.71 41.292,118.11"];
wf [height=0.5,
pos="41.292,18",
shape=ellipse,
width=0.75];
i1 -> wf [dir=back,
pos="s,41.292,71.697 41.292,61.665 41.292,53.054 41.292,43.791 41.292,36.104"];
wf:se -> wf:sw [dir=both,
pos="s,56.292,3 e,26.292,3
65.002,8.3185
92.908,0.389
88.823,-20
41.292,-20
-6.2395,-20
-10.324,0.389
17.582,8.3185"];
}
And this command
neato -n2 -Tpng doubleheaded3.fixed.dot >doubleheaded3.fixed.png
Gives this:
All in all, I'd suggest the pic/gpic/dpic language. Lower-level, but probably easier to use in the long run.
I just learned how to connect nodes and subgraphs here on Stackoverflow. However, I want to connect a node to the containing subgraph:
digraph G {
compound=true;
subgraph cluster0 {
a -> b;
a -> c;
c -> {a b c} [lhead=cluster0];
}
c -> d;
d -> {a b c} [lhead=cluster0];
}
A quick sketch what I mean:
I want to connect d -> {a b c}, but for clarity reasons, I don't want to draw three different arrows, but just one arrow to the grouping of nodes. One way to do that is only list one arrow, like d -> a. That works, but is there a way to "collapse" three arrows into one when the head points to a cluster?
However, c -> {a b c} is not possible to point to a cluster, because c is part of that cluster. Is there a way to go around this?
you will need some scaffolding i.e. invisible node (and maybe edges) e.g.:
digraph top {
compound=true
node[shape=rectangle]
subgraph cluster1 {
a->{b c}
}
c->d
d->b[lhead=cluster1]
ca[shape=point height=0] // make ca invisible
a->ca:n[dir=back ltail=cluster1] // by drawing the arrow backward we get more control of the layout, n and s compass make the edge go smooth when enter and exiting ca
ca:s->c[dir=none] // no arrow on the tail part
}
rendered on viz-js.com:
digraph
{
rankdir=LR
a -> b
c -> b
b -> d
e // unlinked node
}
There are some nodes which are not linked to any of the other nodes in my dot file. Without explicitly using rank to define those nodes, is there any graceful way to put them to the right most position since it is a hard work to reparse the whole relations for finding them out and it is almost impossible to figure it out the maximum depth of the generated graph due to the opaqueness of node rearrangement policy?
You could put the unlinked nodes in a subgraph and use rank="max" to achieve this:
digraph
{
rankdir=LR;
a -> b;
c -> b;
b -> d;
{ rank="max"; e; }
}
I have a set of GraphViz nodes such that:
digraph {
A->B;
A->C;
A->D;
}
But B, C, and D happen sequentially in time!
It would be great if there was some way to indicate the vertical level each node should appear upon (where the number of levels may be unknown beforehand).
Does anyone have thoughts on how to accomplish this?
One option to have a node display on a different rank (vertical level) than an other node is to add invisible edges.
Assigning those nodes the same group indicates graphviz to lay them out in a straight line if possible.
For example:
digraph g{
A;
node[group=a];
B;C;D;
A -> B;
A -> C;
A -> D;
edge[style=invis];
B->C->D;
}
An other option is to have one vertical line of (invisible) nodes, then force the same rank by defining the nodes of the same rank within the same subgraph with rank=same:
digraph g{
{rank=same; l1[style=invis, shape=point]; A;}
{rank=same; l2[style=invis, shape=point]; B;}
{rank=same; l3[style=invis, shape=point]; C;}
{rank=same; l4[style=invis, shape=point]; D;E;F;}
A -> B;
A -> C;
A -> D;
edge[style=invis];
l1->l2->l3->l4;
}
I understand that node ids should be unique within a graphviz (here: dot) file.
However, I wish I could have them be unique within their cluster only, that is, I'd like the following file to produce 4 nodes:
digraph G {
subgraph cluster_clust_one {
node [shape=record];
a [label = "A / 1"];
b [label = "B / 1"];
a -> b;
}
subgraph cluster_clust_two {
node [shape=record];
a [label = "A / 2"];
b [label = "B / 2"];
a -> b;
}
}
However, it doesn't, because the node ids are not unique. Obviously, I can solve this by assigning unique ids, for example by changing cluster_clust_two to
subgraph cluster_clust_two {
node [shape=record];
c [label = "A / 2"];
d [label = "B / 2"];
c -> d;
}
Unfortunately, this would entail changing a script that produces the dot files which I wouldn't want to do if not absolutely necessary. So if there is a flag or something I could set instead, I'd prefer this route.
You could prepend the node name with the name of the cluster like cluster_clust_two__a. It would still mean a change in the generating script.
As far as I know, there is no way to have separate nodes with identical IDs. A sensible workaround was proposed by dgw =)