3
# dotmcl.pl <factor> <in.dot> <out.dot>
4
# <factor> the bigger, the more clusters (values from 1.2 to 3.0)
5
# <in.dot> dot in file to clusterize
6
# <out.dot> dot out file with clusters added
7
# Vladimir Alexiev <vladimir@worklogic.com>
9
# This quick hack takes a dot graph description file, adds clusters using the
10
# mcl utility, and writes to stdout a dot graph amended with "subgraph
11
# cluster_n" declarations that put the nodes in clusters.
12
# dot: http://www.research.att.com/sw/tools/graphviz
13
# mcl: http://members.ams.chello.nl/svandong/thesis/
15
# It passes the input file through "dot -Tplain" so it can parse it more
16
# easily. Restrictions on the input file:
17
# - node names must be plain \w+
18
# - the closing "}" must be on the last line, in first position, and
19
# MUST be the only closing brace in first position in the whole file
22
my $dotin = shift; # why not stdin: because need to read twice
23
my $dotout = shift; # why not stdout: because DOS commingles mcl's stderr into
25
my (@nodes, %node_index, @graph);
26
for (`dot -Tplain $dotin`) {
27
/^node (\w+)/ and do {
29
$node_index{$1} = $#nodes;
32
/^edge (\w+) (\w+)/ and do {
33
$graph[$node_index{$1}][$node_index{$2}] = 1;
34
$graph[$node_index{$2}][$node_index{$1}] = 1;
35
# dot handles digraphs but mcl handles undirected graphs
40
my $mclin = "dotmcl-in.tmp";
41
my $mclout = "dotmcl-out.tmp";
43
open (MCLIN, ">$mclin") or die "can't create $mclin: $!\n";
44
# mcl is a nice program but its input format sucks!
45
print MCLIN << "MCLHEADER";
48
dimensions $ {nodes}x$ {nodes}
55
for (my $i=0; $i<$nodes; $i++) {
57
for (my $j=0; $j<$nodes; $j++)
58
{print MCLIN $j," " if $graph[$i][$j]};
61
print MCLIN << "MCLFOOTER";
66
system("mcl $mclin --silent -v mcl -I $factor -o $mclout")==0 or
67
die "can't run 'mcl $mclin -o $mclout: $!\n";
71
# mcl output format sucks even worse because it can have "continuation lines"
75
# 0 0 1 2 3 4 5 6 7 8 9 12 13 14 15 16 18 19 20
76
# 86 87 88 89 90 91 92 94 95 96 98 105 106 107 109 110 112 113
77
# 115 116 117 118 121 125 127 128 131 132 133 137 138 145 $
78
# 1 28 29 31 32 33 34 35 36 78 93 129 130 134 135 136 $
80
open (MCLOUT, $mclout) or die "can't open $mclout: $!\n";
83
/^\d+(.+)/ and $line = $1;
84
/^ +\d+/ and $line .= $_;
87
my @cl = split' ', $line;
89
unless @cl <= 1; # don't want trivial clusters
94
open (DOTIN, $dotin) or die "can't open $dotin: $!\n";
95
open (DOTOUT, ">$dotout") or die "can't create $dotout: $!\n";
100
for (my $i=0; $i<@cluster; $i++) {
101
print DOTOUT " subgraph cluster_$i {label=\"\" ";
102
for (@{$cluster[$i]}) {print DOTOUT " $nodes[$_]"};