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
loadEdges
command invokes gawk
in order to generate for all edges the corresponding pairs of x/y coordinates (delimited by a blank line) loadWeights
calculates for each edge the middle point and places a label at these coordinates (taking into account the required offset) Addicionally, if you want to add arrows to the edges, you have to do these steps:
Add the arrow style:
set style arrow 1 head filled size screen 0.025,10,40 lc rgb "black" lw 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:
awk
or gawk
and hence platform-independent. A lookup list is created with gnuplot, similar to this answer .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.