简体   繁体   中英

How to plot a tree/graph/web with weighted edges in Gnuplot?

i am plotting a tree in gnuplot as discussed here ( How to plot tree/graph/web data on gnuplot? ). However, i would like to include the edges weight of the tree, ie for each edge i have a number (eg 10, 20, 30, 40) that represents the edge weight. The figure below shows in red the edges weight that i want to plot in gnuplot (i added this using power point).

Can anyone tell me how to plot edges with weight in gnuplot?

在此处输入图像描述

I would propose a slight variation on the answer which you mention in your question. Let's assume that the coordinates of the vertices are stored in a file pnts.dat as follows:

0   5   10
1   20  20
2   15  15
3   30  30
4   40  10

Here, the first column records the corresponding label, while second and third columns contain the x- and y-coordinate, respectively.

The edges could be defined in a separate file edges.dat as:

0   1   30  0   1
1   2   40  0   -2
1   4   20  0   1
1   3   10  0   1

Here, the first two column contain the point indices (they refer to the first column of pnts.dat ). The third column records the weight of a particular edge. Finally, the last two columns contain the x,y displacement of the generated associated label.

With this, the Gnuplot script could look like:

set xr [0:50]   
set yr [0:50]

set size square   

flePnts = 'pnts.dat'
fleEdges = 'edges.dat'

loadEdges = sprintf('< gawk '' \
    FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
    {printf "%%f\t%%f\n%%f\t%%f\n\n", x[$1], y[$1], x[$2], y[$2];} \
'' %s %s', flePnts, fleEdges); 

loadWeights = sprintf('< gawk '' \
    FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
    {printf "%%f\t%%f\t%%s\n", (x[$1]+x[$2])/2 + $4, (y[$1]+y[$2])/2 + $5, $3} \
'' %s %s', flePnts, fleEdges);

plot \
    loadEdges using 1:2 with lines lc rgb "black" lw 2 notitle, \
    flePnts using 2:3:(0.6) with circles fill solid lc rgb "black" notitle, \
    flePnts using 2:3:1 with labels tc rgb "white" font "Arial Bold" notitle, \
    loadWeights using 1:2:3 with labels tc rgb "red" center font "Arial Bold" notitle
  1. the loadEdges command invokes gawk in order to generate for all edges the corresponding pairs of x/y coordinates (delimited by a blank line)
  2. loadWeights calculates for each edge the middle point and places a label at these coordinates (taking into account the required offset)

Finally, one obtains: 在此处输入图片说明

Addicionally, if you want to add arrows to the edges, you have to do these steps:

  1. Add the arrow style:

     set style arrow 1 head filled size screen 0.025,10,40 lc rgb "black" lw 2 
  2. Change the command with lines for with vectors

     loadEdges using 1:2:3:4 with vectors arrowstyle 1 notitle, \\ 

The following image show you the final result:

在此处输入图片说明

And this is the final code:

    set xr [0:50]
    set yr [0:50]

    set size square

    set style arrow 1 head filled size screen 0.025,10,40 lc rgb "black" lw 2

    flePnts = 'pnts.dat'
    fleEdges = 'edges.dat'

    loadEdges = sprintf('< gawk '' \
        FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
        {printf "%%f\t%%f\t%%f\t%%f\n\n", x[$1], y[$1], (x[$2]-x[$1]), (y[$2]-y[$1]);} \
    '' %s %s', flePnts, fleEdges);

    loadWeights = sprintf('< gawk '' \
        FNR==NR{x[$1]=$2;y[$1]=$3;next;} \
        {printf "%%f\t%%f\t%%s\n", (x[$1]+x[$2])/2 + $4, (y[$1]+y[$2])/2 + $5, $3} \
    '' %s %s', flePnts, fleEdges);

    plot \
        loadEdges using 1:2:3:4 with vectors arrowstyle 1  notitle, \
        flePnts using 2:3:(0.6) with circles fill solid lc rgb "black" notitle, \
        flePnts using 2:3:1 with labels tc rgb "white" font "Arial Bold" notitle, \
        loadWeights using 1:2:3 with labels tc rgb "red" center font "Arial Bold" notitle

Here is a suggestion which resembles @ewcz's solution, ie using a list of IDs with x,y coordinates and a list of connections using two IDs. However, with the following differences:

  • all data in one file (in two different blocks addressed with index)
  • a gnuplot-only solution without awk or gawk and hence platform-independent. A lookup list is created with gnuplot, similar to this answer .
  • individual label offsets with rotation angle dA and relative length dR between the points ( dR=0 : at center of connector, dR=-1 : at starting point, dR=1 : at end point). Because of this, is recommended to use set size ratio -1 such that eg a rotation by 45 degrees is visually 45 degrees in the graph.

Data: SO42447683.dat

# ID  x   y
  0   5   10
  1   20  20
  2   15  15
  3   30  30
  4   40  10


# ID1  ID2   weight  dA   dR
  0    1     30       7   0
  1    2     40      20   0
  1    4     20       0   0
  1    3     10       0   0

Script: (works for gnuplot>=5.0.0, without option textbox it works with >=4.6.0)

### plot tree with different labels
reset

FILE = "SO42447683.dat"

set size ratio -1
set key noautotitle
set offsets 0.5,0.5,0.5,0.5
set angle degrees
set style textbox opaque noborder

IdIdxs = XYs = ' '
stats FILE u (IdIdxs=IdIdxs.sprintf("%s:%d ",strcol(1),$0), \
              XYs=XYs.sprintf("%g %g ",$2,$3)) index 0 nooutput
Px(i) = real(word(XYs,2*i+1))
Py(i) = real(word(XYs,2*i+2))

getIdx(col) = (c0=strstrt(IdIdxs,sprintf(" %s:",strcol(col))), \
              c1=strstrt(IdIdxs[c0+1:],' ')+c0, \
              s0=IdIdxs[c0:c1], c2=strstrt(s0,':'), int(s0[c2+1:]))

getLxy(colA,colR) = (idx0=getIdx(1), x0=Px(idx0),y0=Py(idx0), \
                     idx1=getIdx(2), x1=Px(idx1),y1=Py(idx1), \
                     rm = sqrt((x1-x0)**2+(y1-y0)**2)*(column(colR)+1)*0.5, \
                     a = atan2(y1-y0,x1-x0)+column(colA), \
                     Ly = y0+rm*sin(a), Lx=x0+rm*cos(a))

plot FILE index 1 u (idx0=getIdx(1),x0=Px(idx0)):(y0=Py(idx0)): \
         (idx1=getIdx(2),Px(idx1)-x0):(Py(idx1)-y0) w vec lw 2 lc rgb "black" nohead, \
       '' index 0 u 2:3   w p pt 7 ps 4 lc rgb "white",\
       '' index 0 u 2:3   w p pt 6 ps 4 lc rgb "black",\
       '' index 0 u 2:3:1 w labels, \
       '' index 1 u (getLxy(4,5)):(Ly):3 w labels tc rgb "red" boxed
### end of script

Result:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM