gvpack (graphviz) not preserving labels of the individual digraphs - graphviz

There are four dot files (cluster_0, cluster_1, cluster_2, cluster_3) which need to be merged into a single dot file.
The code of the individual dot files is as follows.
digraph cluster_0{
sortv=1;
penwidth=0;pencolor=transparent;
label="1A";
rankdir=LR;
node [fontname = "times-roman-bold",fontsize=12];
edge [fontname = "times-roman-bold",fontsize=12,arrowsize=0.75];
1 [label="1:A"];
2 [label="2:C"];
3 [label="3:G"];
3 -> 1
1 -> 2
3 -> 2
2 -> 3
}
digraph cluster_1 {
sortv=2;
penwidth=0;pencolor=transparent;
label="1B";
node [fontname = "times-roman-bold",fontsize=12];
edge [fontname = "times-roman-bold",fontsize=12,arrowsize=0.75];
rankdir=LR;
11 [label="1:A"];
12 [label="2:C"];
13 [label="3:G"];
14 [label="4:T"];
14 -> 11
11 -> 12
12 -> 13
12 -> 14
13 -> 14
}
digraph cluster_2 {
rankdir=LR;
sortv=3;
penwidth=0;pencolor=transparent;
label="1C";
node [fontname = "times-roman-bold",fontsize=12];
edge [fontname = "times-roman-bold",fontsize=12,arrowsize=0.75];
21 [label="1:A"];
22 [label="2:C"];
23 [label="3:G"];
24 [label="4:T"];
25 [label="5:A"];
24 -> 21
21 -> 22
21 -> 25
25 -> 22
22 -> 23
23 -> 24
}
digraph cluster_3{
sortv=4;
penwidth=0;pencolor=transparent;
label="1D"
node [fontname = "times-roman-bold",fontsize=12];
edge [fontname = "times-roman-bold",fontsize=12,arrowsize=0.75];
rankdir=LR;
31 [label="1:A"];
32 [label="2:C"];
33 [label="3:G"];
31:c -> 31:w
32 -> 31 [dir=both,len=1.25];
33 -> 31 [dir=both,];
32 -> 32
33 -> 32 [dir=both,];
33 -> 33
}
To generate a merged single dot file ...I ran the following command.
neato -Gstart=5 cluster_0.dot cluster_1.dot cluster_2.dot cluster_3.dot | gvpack -array_u4 | neato -n2 -s -Teps -o merge.eps
merge.eps came perfectly well but the labels of the individual graphs went missing. How can we preserve the labels of the individual graphs in the output merge file ? Can anyone help to fix this ?
Here I am attaching the single individual file where the label is shown
I compiled the individual file with the following command.
neato -Gstart=5 cluster_0.dot -Teps -o cluster_0.eps
Also I am attaching the merge output file which removed the labels of the graphs.

This is not an answer but rather sharing experiences: As it turns out while experimenting with various options, it seems to be the neato engine that supresses the labels. If you use dot, you may not get the exact layout you want but you get the labels:
dot -Gstart=5 cluster_0.dot cluster_1.dot cluster_2.dot cluster_3.dot | gvpack -array_u4 | dot -n2 -s -T jpg -o merge.jpg
gives you
My personal preference would by to have one master file so.m4
digraph so
{
define(`digraph',`subgraph')
rankdir=LR;
include(cluster_0.dot)
include(cluster_1.dot)
include(cluster_2.dot)
include(cluster_3.dot)
}
that I process with
m4 so.m4 > so.dot
In the resulting so.dot file, I have all clusters combined, and I can go to the next step (here producing a JPG) with a simple
dot -T png -o so.png so.dot
The advantage of that is that you can use the master file for "global options". I think it is easier to maintain and less unwieldy than the command with all the pipes and options. But that's a matter of taste.
With the option rankdir=LR; this version is produced:
Have fun - happy to do more but I'd need to know more about your project.

Related

How to get data in regex in between multiple pair of indexes/positions

I want to get chunk of data from sentence in between multiple pair of positions.
"There is forest and hills. That place is amazing"
out of this sentence I want data in between the indexes
8 - 13 -> forest
18 - 23 -> hills
so output will be -> forest hills

GraphViz: trouble with grid layout using pos attribute

I'm trying to align this graph, whose purpose is to show the results of sorting.
I need a general solution.
The dot file is generated, so I can't use hand tweaking.
I've tried pos, pos with !, dot -n, dot -Kneato, dot -Kfdp, and other things.
Here is the source (laid out for human grokkability):
digraph x {
rankdir=LR
11 [pos="1,1"] 21 [pos="2,1"] 31 [pos="3,1"] 41 [pos="4,1"]
12 [pos="1,2"] 22 [pos="2,2"] 32 [pos="3,2"] 42 [pos="4,2"]
13 [pos="1,3"] 23 [pos="2,3"] 33 [pos="3,3"]
14 [pos="1,4"] 24 [pos="2,4"]
11:e -> 21:w 21:e -> 31:w 31:e -> 41:w
12:e -> 22:w 22:e -> 32:w 32:e -> 42:w
22:e -> 31:w
# 41:e -> 21:w
# 41:e -> 22:w
# 12:e -> 12:w
# 32:e -> 32:w
13:e -> 23:w 23:e -> 33:w
14:e -> 24:w
# 13:e -> 14:w
# 14:e -> 13:w
# 23:e -> 24:w
# 24:e -> 23:w
}
In the first rendering, you'll see essentially how it should look (except for the shuffled row order).
Later renderings, which will include cyclic edges, should retain this basic layout.
dot -Tpng -o test.png test.dot:
Now some renderings after uncommenting the cyclic edges.
dot -Tpng -o test.png test.dot:
dot -Kneato -Tpng -o test.png test.dot:
dot -Kfdp -Tpng -o test.png test.dot:
Not using pos as in my experience (confirmed by your attempts), it does not work well with the dot engine, and with neato and others I have never been able to produce something like a grid layout.
Three general steps to get closer with dot:
align the nodes vertically with rank = same
align the nodes horizontally using weight = 10 (or any other arbitrary number that works)
add invisible vertical struts as necessary (here 14 -> 12)
make sure that you point the edges following the established hierarchy, meaning explicitly using dir = back where appropriate
My shot at your situation:
digraph
{
rankdir = LR;
{rank = same; 14 -> 13 -> 12 -> 11[ style = invis ] }
{rank = same; 24 -> 23 -> 22 -> 21[ style = invis ] }
{rank = same; 33 -> 32 -> 31[ style = invis ] }
{rank = same; 42 -> 41[ style = invis ] }
14 -> 24[ weight = 10 ];
13 -> 23 -> 33[ weight = 10 ];
12 -> 22 -> 32 -> 42[ weight = 10 ];
11 -> 21 -> 31 -> 41[ weight = 10 ];
22:e -> 31:w;
12:e -> 12:w
32:e -> 32:w
21:se -> 41:sw[ dir = back ];
22:se -> 41:sw[ dir = back ];
14 -> 12 [ color = red ];
14:w -> 13:w
13:e -> 14:e[ dir = back ];
24:w -> 23:w
23:e -> 24:e[ dir = back ];
}
which yields

merging linear lists - reconstruct railway network

I need to reconstruct the sequence of stations in a railway network from the sequences of single trips requested from a arbitrary station. There's no direction given in the data. But every request returns an terminal stop. The sequences of single trips can have gaps.
The (end-) result is always a linear list - forking is not allowed.
For example:
Result trips from requested station "4" :
4 - 3 - 2 - 1
4 - 1
4 - 5 - 6
4 - 8 - 9
4 - 6 - 7 - 8 - 9
manually reordered:
1 - 2 - 3 - 4
1 - 4
- 4 - 5 - 6
- 4 - 8 - 9
- 4 - 6 - 7 - 8 - 9
After merging result should be:
1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9
start/stop: 1, 9
Is there an algorithm to calculate the resulting "rope of pearls" list? I tried to figure it out with perls graph-module, but no luck. My books on algorithms doesn't help either.
I think, there are pathologic cases, where multiple solutions are possible, depending on input data.
Maybe someone has an idea to solve it!
As you see in the answers, there is more than one solution. So here's a real-world dataset:
2204236 -> 2200007 -> 2200001
2204236 -> 2203095 -> 2203976 -> 2200225 -> 2200007 -> 2200001
2204236 -> 2204805 -> 2204813 -> 2204401 -> 2219633 -> 2204476 -> 2202024 -> 2202508 -> 2202110 -> 2202026
2204236 -> 2204813 -> 2204401 -> 2219633 -> 2202508 -> 2202110 -> 2202026 -> 3011047 -> 3011048 -> 3011049
2204236 -> 2204813 -> 2204401 -> 2219633 -> 2204476 -> 2202024 -> 2202508 -> 2202110 -> 2202352 -> 2202026
2204236 -> 2204813 -> 2204401 -> 2219633 -> 2204476 -> 2202024 -> 2202508 -> 2209637 -> 2202110
solution of the example data with perl:
use Graph::Directed;
use Graph::Traversal::DFS;
my $g = Graph::Directed->new;
$g->add_path(1,2,3,4);
$g->add_path(1,4);
$g->add_path(4,5,6);
$g->add_path(4,8,9);
$g->add_path(4,6,7,8,9);
print "The graph is $g\n";
my #topo = $g->toposort;
print "g toposorted = #topo\n";
Output
> The graph is 1-2,1-4,2-3,3-4,4-5,4-6,4-8,5-6,6-7,7-8,8-9
> g toposorted = 1 2 3 4 5 6 7 8 9
Using the other direction
$g->add_path(4,3,2,1);
$g->add_path(4,1);
$g->add_path(4,5,6);
$g->add_path(4,8,9);
$g->add_path(4,6,7,8,9);
reveals the second solution
The graph is 2-1,3-2,4-1,4-3,4-5,4-6,4-8,5-6,6-7,7-8,8-9
g toposorted = 4 3 2 1 5 6 7 8 9
Treat the lists node links in a graph. 4-3-2-1 should mean 4 must come before 3, 3 before 2 and 2 before 1. So add arcs from 4 to 3, 3 to 2, 2 to 1.
Once you have all of those you run a topological sort(look it up on wikipedia) on the resulting graph. This will guarantee that the order you get will always respect the partial orderings you are given.
The only case when you are not going to find a solution is when the data is contradicting itself (if you have 4-3-2 and 4-2-3 there's no possible ordering).
You are right, there are multiple cases. Another good solution is 4-5-6-7-8-9-3-2-1, for your example.
Terminal stop station is articulation node and it splits graph into multiple partitions: all nodes inside partition are reachable from one another, nodes in different partitions are reachable only via known terminal stop station. Number of partitions is 2 in your example, but may be much larger, e.g. consider star-like structure 1 - 2, 1 - 3, 1 - 4, 1 - 5.
First of all you need to enumerate partitions. You treat your graph as undirected graph and run DFS from stop station in each of directions. At first run you discover partition #1, at second run partition #2 and so on.
Then you treat you graph as directed with stop station as root node for all partitions and run topological sorting (TS) for each of partitions.
Possible outcomes:
TS for one of partitions fails. This means there is no solution.
Number of partitions is one and TS for it succeeds. Solution is unique.
Number of partitions is more than one and TS succeeds for all of them. This means there are multiple solutions. To get any single valid result, you choose some partition and declare that it contains another terminal station. All other partitions are inserted into the first one in between arbitrary pair of nodes.

How to enforce sub graphs to be on the same horizontal line in Graphviz

I'm using graphviz (dot) to generate time expanded graph to use in my master thesis. However, my drawing results the following graph:
As you can see, the third line is a little bit shifted to the right.I want all the lines in the same horizontal line. Also i want the x.th node in each line to stay at the same horizontal line of other x.th nodes of lines. Changing the edge weights would not helped me.
I could not find anything related to this problem so far.
What i want to achieve is something like this:
Here is my code:
digraph G {
1[label="1"]
2[label="1"]
3[label="1"]
4[label="1"]
5[label="1"]
6[label="1"]
7[label="2"]
8[label="2"]
9[label="2"]
10[label="2"]
11[label="2"]
12[label="2"]
13[label="3"]
14[label="3"]
15[label="3"]
16[label="3"]
17[label="3"]
18[label="3"]
19[label="4"]
20[label="4"]
21[label="4"]
22[label="4"]
23[label="4"]
24[label="4"]
rankdir="LR";
node[width=0.15, height=0.15, shape=point];
edge[weight=500, label="1"];
1 -> 2 -> 3 -> 4 -> 5 -> 6 ;
7 -> 8 -> 9 -> 10 -> 11 -> 12 ;
13 -> 14 -> 15 -> 16 -> 17 -> 18 ;
19 -> 20 -> 21 -> 22 -> 23 -> 24 ;
edge[weight=3];
1 -> 9;
2 -> 9;
3 -> 11;
13 -> 22;
14 -> 22;
15 -> 24;
edge[weight=1];
1 -> 14;
2 -> 15;
3 -> 17;
7 -> 21;
8 -> 23;
9 -> 22;
}
Any help would be appreciated.
Instead of using weight try using the attribute constraint=false for all edges which go from one "line" to another.
Setting constraint to false makes graphviz to not consider those edges when laying out the nodes of the graph.
See also this very similar question & answer
As far as I know, the only way is to specify an explicit position for each individual node.
See: How to force node position (x and y) in graphviz

children order in graphviz tree

I have following tree:
digraph G {
subgraph cluster0{
37[label="+"];
42[label="a"];
44[label="b"];
47[label="*"];
46[label="c"];
49[label="d"];
51[label="e"];
53[label="f"];
55[label="g"];
57[label="h"];
61[label="*"];
60[label="i"];
63[label="j"];
37 -> 42[label="c"];
37 -> 44[label="c"];
37 -> 47[label="c"];
37 -> 61[label="c"];
42 -> 37[label="p"];
44 -> 37[label="p"];
47 -> 37[label="p"];
47 -> 46[label="c"];
47 -> 49[label="c"];
47 -> 51[label="c"];
47 -> 53[label="c"];
47 -> 55[label="c"];
47 -> 57[label="c"];
46 -> 47[label="p"];
49 -> 47[label="p"];
51 -> 47[label="p"];
53 -> 47[label="p"];
55 -> 47[label="p"];
57 -> 47[label="p"];
61 -> 37[label="p"];
61 -> 60[label="c"];
61 -> 63[label="c"];
60 -> 61[label="p"];
63 -> 61[label="p"];
}
}
Output is here: http://i.imgur.com/q1qXkCT.png
Order of children in first * subtree is: G H C D E F, but it should be C D E F G H.
I have noticed that if I delete subgraph cluster0{ the order is right, but I can't do it this way.
Can you suggest any other solution?
Graphviz attempts to retain the lexical ordering of nodes when there is no other constraint. However, the edge labels can affect placement as they take up space and can push nodes around.
If you have a specific order that is essential, then try something like
{ rank = same;
46 -> 49 -> 51 -> 53 -> 55 -> 57 [style = invis];
}
to introduce the additional ordering constraint into the graph.
You need to be careful with this though, as it can distort more complex graphs in ways that are very difficult to predict.
Clusters further complicate matters in larger graphs as they implicitly attempt to make the subgraph more compact and introduce a bounding box that non-cluster members cannot cross.

Resources