What is the best way to draw large graph using graphvis
Asked Answered
V

4

1

I need to draw large dataset on image, I used graphvis command lines with all available tools (dot, neato, twopi .. etc) but the result is not readable and contains overlapping.

What I need is display the nodes with labels on the edges, with minimum overlapping so the graph can be readable and also printed on A4 or A3 paper.

I used the options overlap=false, splines=true in neato and same overlapping result.

Here is the dataset:

graph {
    graph [ bgcolor=ivory2, overlap=false, splines=true, ranksep ="2.75"]
    {node [width=1,height=1,shape=circle,style=filled,color=skyblue] "ECNY" }
    edge [ len=2, sep=5] 
    "DANA" -- "HMRN" -- "ECNY" -- "NORI" -- "MAJZ" -- "RSFH" -- "DANA" [label ="LD1-25-A01",  penwidth =3 , color="#156163"]
    "DANA" -- "HMRN" -- "ECNY" -- "NORI" -- "MAJZ" -- "RSFH" -- "DANA" [label ="LD1-25-A02",  penwidth =3 , color="#30a1f9"]
    "DANA" -- "MAJZ" -- "ECNY" -- "HMRN" -- "DANA" [label ="LD1-25-A03",  penwidth =3 , color="#ec591d"]
    "DANA" -- "MAJZ" -- "ECNY" -- "HMRN" -- "DANA" [label ="LD1-25-A04",  penwidth =3 , color="#263a5f"]
    "DANA" -- "ECNY" -- "DANA" [label ="LD3-25-A02",  penwidth =3 , color="#a3517c"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "HMRN" [label ="LD1-25-H01",  penwidth =3 , color="#800d83"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" [label ="LD1-25-H02",  penwidth =3 , color="#89e15a"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" [label ="LD3-25-H03",  penwidth =3 , color="#74ed0e"]
    "HMRN" -- "ECNY" -- "HMRN" [label ="JED-10-H08",  penwidth =3 , color="#e8e786"]
    "HMRN" -- "ECNY" -- "MAJZ" -- "DANA" -- "HMRN" [label ="LD1-25-H04",  penwidth =3 , color="#e1f559"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A02",  penwidth =3 , color="#8f7964"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A03",  penwidth =3 , color="#9058f0"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-A04",  penwidth =3 , color="#b537b7"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-A05",  penwidth =3 , color="#fc2c2a"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A06",  penwidth =3 , color="#36309c"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-A07",  penwidth =3 , color="#25a571"]
    "ECNY" -- "OBHR" -- "ECNY" [label ="JED-10-A26",  penwidth =3 , color="#1a6077"]
    "ECNY" -- "2820" -- "ECNY" [label ="JED-25-A03",  penwidth =3 , color="#8bce8c"]
    "ECNY" -- "2138" -- "2129" -- "ECNY" [label ="JED-25-A04",  penwidth =3 , color="#9b9afa"]
    "ECNY" -- "2017" -- "2013" -- "ECNY" [label ="JED-25-A05",  penwidth =3 , color="#5ea9aa"]
    "ECNY" -- "2027" -- "2128" -- "ECNY" [label ="JED-25-A22",  penwidth =3 , color="#c0c4d4"]
    "ECNY" -- "2130" -- "2137" -- "ECNY" [label ="JED-25-A27",  penwidth =3 , color="#781ce0"]
    "ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-A01",  penwidth =3 , color="#fd5c5a"]
    "ECNY" -- "HMRN" -- "ZJ01" -- "ECNY" [label ="JED-10-H03",  penwidth =3 , color="#32e13b"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-10-H04",  penwidth =3 , color="#487f94"]
    "ECNY" -- "2341" -- "2235" -- "2233" -- "ECNY" [label ="JED-10-H05",  penwidth =3 , color="#82ae2d"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-H06",  penwidth =3 , color="#f4651c"]
    "ECNY" -- "HMRN" -- "SBCB" -- "ECNY" [label ="JED-10-H07",  penwidth =3 , color="#23dd41"]
    "ECNY" -- "HMRN" -- "OBHR" -- "ECNY" [label ="JED-10-H37",  penwidth =3 , color="#521f43"]
    "ECNY" -- "PROJECT" -- "ECNY" [label ="JED-10-H49",  penwidth =3 , color="#0a4bf1"]
    "ECNY" -- "2234" -- "2246" -- "2245" -- "2320" -- "ECNY" [label ="JED-25-H01",  penwidth =3 , color="#6127e4"]
    "ECNY" -- "2842" -- "2030" -- "ECNY" [label ="JED-25-H03",  penwidth =3 , color="#ce1f98"]
    "ECNY" -- "2170" -- "2166" -- "ECNY" [label ="JED-25-H06",  penwidth =3 , color="#aeb0ce"]
    "ECNY" -- "2158" -- "2144" -- "ECNY" [label ="JED-25-H11",  penwidth =3 , color="#9ef618"]
    "ECNY" -- "5824" -- "2011" -- "ECNY" [label ="JED-25-H15",  penwidth =3 , color="#b2d524"]
    "ECNY" -- "2010" -- "2830" -- "2198" -- "ECNY" [label ="JED-25-H16",  penwidth =3 , color="#53e7ae"]
    "ECNY" -- "2179" -- "ECNY" [label ="JED-25-H17",  penwidth =3 , color="#149169"]
    "ECNY" -- "2211" -- "ECNY" [label ="JED-25-H19",  penwidth =3 , color="#15a51b"]
    "ECNY" -- "2316" -- "ECNY" [label ="JED-25-H20",  penwidth =3 , color="#e91d18"]
    "ECNY" -- "2203" -- "ECNY" [label ="JED-25-H22",  penwidth =3 , color="#38a23a"]
    "ECNY" -- "SBCB" -- "JFCC" -- "ECNY" [label ="JED-25-H33",  penwidth =3 , color="#a1abf4"]
    "ECNY" -- "HMRN" -- "ECNY" [label ="JED-25-H41",  penwidth =3 , color="#c14ff8"]
    "ECNY" -- "TAIF" -- "SNFN" -- "NORI" -- "ECNY" [label ="LD1-10-H04",  penwidth =3 , color="#75fb4f"]
    "ECNY" -- "MAJZ" -- "DANA" -- "TWRN" -- "HMRN" -- "ECNY" [label ="LD1-25-H03",  penwidth =3 , color="#52d1c8"]
    "ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-H01",  penwidth =3 , color="#498a16"]
    "ECNY" -- "DANA" -- "ECNY" [label ="LD3-25-H02",  penwidth =3 , color="#70f831"]
    "ECNY" -- "2310" -- "5880" -- "5301" -- "2248" -- "ECNY" [label ="JED-10-H17",  penwidth =3 , color="#ebb4e1"]
    "SBCB" -- "ECNY" -- "HMRN" -- "JELS" -- "ROMN" -- "OBHR" -- "SAFA" -- "SBCB" [label ="JED-W40-A01",  penwidth =3 , color="#7ff59c"]
    "SBCB" -- "SAFA" -- "OBHR" -- "HMRN" -- "ECNY" -- "SBCB" [label ="JED-10-H35",  penwidth =3 , color="#e817b9"]
    "2171" -- "ECNY" -- "2171" [label ="JED-10-H19",  penwidth =3 , color="#bf1252"]
    "ABHA" -- "ECNY" -- "DANA" -- "ABHA" [label ="LD3-10-H01",  penwidth =3 , color="#8b60ae"]
    "MAJZ" -- "ECNY" -- "DANA" -- "2510" -- "MAJZ" [label ="LD1-10-H02",  penwidth =3 , color="#1e3c55"]
    "2209" -- "2206" -- "ECNY" -- "2209" [label ="JED-25-H02",  penwidth =3 , color="#1b6092"]
    }

this is one of the output when using these options (in neato):

graph [ bgcolor=ivory2, overlap=false, splines=true, ranksep ="2.75"]

{node [width=1,height=1,shape=circle,style=filled,color=skyblue] "ECNY" }

edge [ len=2, sep=5]

enter image description here

also this when make overlap=scale but still the image is not readable!

overlap=scale, sep=\"+25,25\", splines=true, rankdir=\"TB\"

enter image description here

so what other attributes can enhance this graph ?

Valdavaldas answered 23/4, 2013 at 15:47 Comment(0)
B
4

Inevitably, as the number of nodes and edges increase, we will eventually end up without enough space to have a compact but nevertheless clear graph. However, there are some things we can do to improve matters, I think. In this case, we can take advantage of the fact that all the sequences of edges form loops that return to "ECNY".

First, I weighted the edges that are closer to "ECNY" less (so that they are more stretchy) and made them longer by default (so that the middle of the graph was more spread out), and conversely with the edges that are further from "ECNY".

Second, I labelled each loop only once, with the label being on the edge as far away from "ECNY" in the loop as I could get it.

I made these changes programmatically with a Python script adjweight.py as follows:

import sys, re, math

for line in sys.stdin:
    line = line.rstrip()
    if re.match(' +"',line):
        loop, attr = line.split(" [")
        loopli = loop.split(" -- ")[1:] 
        # We take all but the first node, to eliminate repeats
        # then we put the list of edges together with "ECNY" first and last.
        i = loopli.index('"ECNY"')
        loopli = loopli[i:] + loopli[:i] + [loopli[i]]
        n = len(loopli)

        # Now we write the multi-edge lines as individual lines so that we can 
        # give each edge an individual weight and length

        for i in range(n-1):
            # We weight edges that are furthest from the center (i.e. those with 
            # numbers closest to n/2) highest and those that are closest to the
            # center are weighted lowest.
            wt = (n/2)/(abs(n/2 - (i+1))+1)
            edgelength = 1/wt
            if i - n//2 + 1 != 0:
                # This edge is the furthest from the center in this loop, so we 
                # label this edge (but not the other edges in the loop)
                attr = ",".join(attr.split(",")[1:])
            # We raise the weights and edge lengths to different powers to adjust
            # the distribution of nodes across the "diameter" of the graph
            print ("    %s -- %s [weight = %f, len = %f, %s" % (
                loopli[i],loopli[i+1],wt**3,edgelength**2,attr))
    else:
        print (line)

... which can be run with python adjweight.py <large.dot >large3.dot, where large.dot is the .dot file shown in the question.

Changing the fontsize for the edges to 10 (compared to the default of 14) and running large3.dot through neato gave me the following graph: enter image description here

This has spread the nodes more evenly around the page and it is much less cluttered by edge labels, so it seems like an improvement to me. Edge labels still overlap a few nodes and (particularly in the top right of the graph) other edge labels because the overlap parameter only affects nodes and edge lines, not edge labels.

Tweaking the relative lengths and weights of edges as they relate to the distance from "ECNY" might help improve the graph a bit more.

Bignonia answered 1/5, 2013 at 2:22 Comment(3)
After reflecting overnight, I think that to get much better than this, I think it would be necessary to draw the network by hand (if there is only one to draw) using a style like the London Underground map (rodcorp.typepad.com/rodcorp/images/tube_walklines_final_lm.gif).Bignonia
so the hand drawing is the best options in this case of graph ?Valdavaldas
A hand-drawn graph always has the potential to be more attractive than a software-drawn graph. Using neato is quicker (even if one has to re-weight and re-size edges, as I did in my solution) so it is the best option if there are many similar graphs to draw. If you have the time and you need the graph to be really easy to read and understand, however, laying it out by hand will give a better result, especially if something like the London Underground map (which has loops in it like your example) is used as a style guide.Bignonia
D
1

i need to visualize all the path form certain node to other nodes, so my problem about visualizing nodes not on the simplification. all right you already visualize all the path from certain node to other nodes But AS you said ** the result is not readable and contains overlapping**. i think what you need is to make this visualize clear my next advice to you try visualize your graph by hand on small data using (3 dimension graph) then code it or try to find attributes to visualize it on 3d if it work well on small data.

i just try to think how to help in this problem so all this are just suggestion and open questions to make you find answer on your question.

Doane answered 4/5, 2013 at 11:36 Comment(0)
D
0

Why you not try to reduce data on your graph first (i.e:even if you get your implementation - it is hard to follow the graph)and the main idea of representing data on a graph is simplification and you will loss it )So My ADVICE TRY TO REDUCE DATA ON Your GRAPH.

Doane answered 4/5, 2013 at 11:1 Comment(1)
I need to visualize all the path form certain node to other nodes, so my problem about visualizing nodes not on the simplification.Valdavaldas
U
0

I recommend using software/framework that has the popular force directed layout algorithms (http://en.wikipedia.org/wiki/Force-directed_graph_drawing), the most popular of which are Fruchterman-Reingold and Kamada-Kawai. I've used R (http://www.r-project.org/) with the igraph package. I know this is kind of not answering your question since you said you were using graphvis, but using force-directed algorithms is your best bet.

Ummersen answered 23/9, 2013 at 19:48 Comment(1)
graphviz has fdp and sfdp tools for this purposeMettlesome

© 2022 - 2024 — McMap. All rights reserved.