Row title in multiplot - gnuplot

In the figure below, each row corresponds to a different case/parameter. Parameters from top to bottom are nmesh-2, nmesh-4, nmesh-6, nmesh-8. I would like to write each parameter to the left of ylabel or Elapsed time. In other words, I want a "row title". It would also be nice if parameter name was bigger than and rotated as Elapsed time. My code includes filenames but in case I included it as well.
set key autotitle columnhead
set boxwidth 0.5
set style fill transparent solid
set nokey
set terminal wxt size 1900,990
set multiplot layout 4, 7
set xtics rotate by -45
np = "8 12 16 20 24 28 32"
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel 'Elapsed time'
}
else {
unset ylabel
}
set title sprintf("np-%s", word(np, IDX))
plot sprintf("run-1/np-%s/nmesh-2/load-estim-0/hole-cut-implicit/cpupertask-3/ncell-11/dominant-0.dat", word(np, IDX)) u 2:xtic(1) with boxes
}
set notitle
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel 'Elapsed time'
}
else {
unset ylabel
}
plot sprintf("run-1/np-%s/nmesh-4/load-estim-0/hole-cut-implicit/cpupertask-3/ncell-11/dominant-0.dat", word(np, IDX)) u 2:xtic(1) with boxes
}
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel 'Elapsed time'
}
else {
unset ylabel
}
plot sprintf("run-1/np-%s/nmesh-6/load-estim-0/hole-cut-implicit/cpupertask-3/ncell-11/dominant-0.dat", word(np, IDX)) u 2:xtic(1) with boxes
}
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel 'Elapsed time'
}
else {
unset ylabel
}
plot sprintf("run-1/np-%s/nmesh-10/load-estim-0/hole-cut-implicit/cpupertask-3/ncell-11/dominant-0.dat", word(np, IDX)) u 2:xtic(1) with boxes
}

Perhaps the easiest approach to do this would be to use a multiline y label:
set ylabel "nmesh-2\n\nElapsed time"
However, the flexibility of this solution is rather limited. As an alternative, one might use set multiplot with the margins option in order to make sure that there is enough space for the "row titles" in the global left margin of the entire multiplot, calculate the coordinates of the individual "row titles" in screen coordinates manually and render them within the last plot:
set terminal pngcairo size 1900,990 enhanced
set output 'fig.png'
numOfRows = 4
marginLeft = 0.1
marginRight = marginLeft/2
marginV = 0.1
plotSpacing = marginV / 2
plotHeight = (1. - 2*marginV - (numOfRows-1)*plotSpacing) / numOfRows
labelPos(i) = 1. - (marginV + plotHeight/2 + i*(plotHeight + plotSpacing))
params = "nmesh-2 nmesh-4 nmesh-6 nmesh-8"
set multiplot layout numOfRows,7 margins marginLeft,1-marginRight,marginV,1-marginV spacing plotSpacing
set key autotitle columnhead
set boxwidth 0.5
set style fill transparent solid
set nokey
set xtics rotate by -45
np = "8 12 16 20 24 28 32"
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel 'Elapsed time'
}
else {
unset ylabel
}
set title sprintf("np-%s", word(np, IDX))
plot sin(x) w l
}
set notitle
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel 'Elapsed time'
}
else {
unset ylabel
}
plot sin(x) w l
}
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel 'Elapsed time'
}
else {
unset ylabel
}
plot sin(x) w l
}
do for [IDX=1:7] {
if (IDX == 1) {
set ylabel "Elapsed time"
}
else {
unset ylabel
}
if (IDX == 7) {
do for [j=1:4] {
set label word(params, j) at screen marginLeft/2, screen labelPos(j-1) offset char -2, 0 center rotate by 90 font "Arial,16"
}
}
plot sin(x) w l
}
This should yield:

Related

gnuplot command not valid

I am trying to create a gif of the movement of two circular objets.
Below is my choc.gnu file, where data_choc.txt contains four columns of the object's positions.
When typing in load "choc.gnu", it says that line 12 is an invalid command.
Any ideas why?
Thanks a lot!
reset
set datafile separator " "
set terminal gif animate delay 1
set output 'choc.gif'
set xrange [-0.1:1.7]
set yrange [-0.3:1.05]
set size ratio -1
do for [ii=1:300] {
plot 'data_choc.txt' u 1:2 every ::1::ii w l lt rgb "red",
'' u 1:2:(0.051111) every ::ii::ii w circle lt rgb "red",
'' u 3:4 every ::1::ii w l lt rgb "blue",
'' u 3:4:(0.05) every ::ii::ii w circle lt rgb "blue"
}
In order to continue a command across multiple lines, you must end the partial lines with a trailing \ character. So
do for [ii=1:300] {
plot 'data_choc.txt' u 1:2 every ::1::ii w l lt rgb "red", \
'' u 1:2:(0.051111) every ::ii::ii w circle lt rgb "red", \
'' u 3:4 every ::1::ii w l lt rgb "blue", \
'' u 3:4:(0.05) every ::ii::ii w circle lt rgb "blue"
}

gnuplot: arrows between circles

How can I draw arrows between circles where
the arrows point to the centers of the circles,
but have reduced length such that they only touch the circumference,
independent of the terminal size ratio?
Sounds easy, but I haven't found a shorter solution than the example below. You need to to some coordinate transformations between axes coordinates and terminal coordinates.
For this, you need to know the terminal size of the plot and you'll get these values into the GPVAL_... variables only after plotting you have to do a dummy plot first and then replot.
If I overlooked some obvious and simpler procedure, please let me know.
Code:
### arrows touching circles
reset session
# Factor between axes and terminal coordinates
FactorX(n) = real(GPVAL_X_MAX-GPVAL_X_MIN)/(GPVAL_TERM_XMAX-GPVAL_TERM_XMIN)
FactorY(n) = real(GPVAL_Y_MAX-GPVAL_Y_MIN)/(GPVAL_TERM_YMAX-GPVAL_TERM_YMIN)
# Axis coordinates to terminal coordinates
AxisToTermX(x) = (x-GPVAL_X_MIN)/FactorX(0)+GPVAL_TERM_XMIN
AxisToTermY(y) = (y-GPVAL_Y_MIN)/FactorY(0)+GPVAL_TERM_YMIN
xt(x) = AxisToTermX(x)
yt(y) = AxisToTermY(y)
rt(r) = r/FactorX(0)
Lt(x1,y1,x2,y2) = sqrt((xt(x2)-xt(x1))**2 + (yt(y2)-yt(y1))**2)
# terminal coordinates reduced by radii
x1tr(x1,y1,r1,x2,y2,r2) = rt(r1)*(xt(x2)-xt(x1))/Lt(x1,y1,x2,y2)+xt(x1)
y1tr(x1,y1,r1,x2,y2,r2) = rt(r1)*(yt(y2)-yt(y1))/Lt(x1,y1,x2,y2)+yt(y1)
x2tr(x1,y1,r1,x2,y2,r2) = (Lt(x1,y1,x2,y2)-rt(r2))*(xt(x2)-xt(x1))/Lt(x1,y1,x2,y2) + xt(x1)
y2tr(x1,y1,r1,x2,y2,r2) = (Lt(x1,y1,x2,y2)-rt(r2))*(yt(y2)-yt(y1))/Lt(x1,y1,x2,y2) + yt(y1)
# Terminal coordinates to axis coordinates
TermToAxisX(xt) = real(xt-GPVAL_TERM_XMIN)*FactorX(0)+GPVAL_X_MIN
TermToAxisY(yt) = real(yt-GPVAL_TERM_YMIN)*FactorY(0)+GPVAL_Y_MIN
# axis coordinates reduced by radii
x1r(x1,y1,r1,x2,y2,r2) = TermToAxisX(x1tr(x1,y1,r1,x2,y2,r2))
y1r(x1,y1,r1,x2,y2,r2) = TermToAxisY(y1tr(x1,y1,r1,x2,y2,r2))
x2r(x1,y1,r1,x2,y2,r2) = TermToAxisX(x2tr(x1,y1,r1,x2,y2,r2))
y2r(x1,y1,r1,x2,y2,r2) = TermToAxisY(y2tr(x1,y1,r1,x2,y2,r2))
# dummy plot
set xrange [-10:10]
set yrange [-10:10]
plot NaN notitle
$Data <<EOD
0 0 1.0
-6 2 3.0
0 5 0.75
7 -8 2.0
5 8 1.5
EOD
N = |$Data| # length of datablock
# draw N circles
do for [i=0:N-1] {
set obj i+1 circle at word($Data[i+1],1),word($Data[i+1],2) size word($Data[i+1],3) fc "blue"
}
# draw N arrows
do for [i=0:N-1] {
x1 = word($Data[i+1],1)
y1 = word($Data[i+1],2)
r1 = word($Data[i+1],3)
x2 = word($Data[(i+1)%N+1],1)
y2 = word($Data[(i+1)%N+1],2)
r2 = word($Data[(i+1)%N+1],3)
set arrow i+1 from x1r(x1,y1,r1,x2,y2,r2), y1r(x1,y1,r1,x2,y2,r2) \
to x2r(x1,y1,r1,x2,y2,r2), y2r(x1,y1,r1,x2,y2,r2) heads lc "red"
}
replot
### end of code
Result: (wxt size 600,600)
The same code with (wxt size 700,300)

symmetric logarithmic plot (symlog)

How would you make a symlog plot in gnuplot?
matplolib has such a feature:
I'm thinking about some axis + tics manipulation or multiplot where on panel has reversed axis.
Finally, I need this for the z axis (cbrange) the show the residuals as an image.
symlog(x) = (-1 < x && x < 1) ? x/10. \
: (x < 0) ? -log(-x) - 0.1 \
: log(x) + 0.1
invsymlog(x) = (-0.1 < x && x < 0.1) ? x*10. \
: (x < 0) ? -exp(-(x+0.1)) \
: exp(x-0.1)
set xlabel "Symlog axis"
set nonlinear x via symlog(x) inv invsymlog(x)
set xrange [-4*pi : 4*pi]
set sample 500
set xtics -10,1,10 nomirror
set xtics add ("//" 0)
set xtics font ",10"
plot x*cos(x)
The region between -1 and +1 is linear, the rest is log scale.

Break y-axis in three parts in gnuplot

I try to plot some data that has a huge gap in the y axis which I wish to exclude from the graph.
noises:
I found this guide to split the graph into two parts, which works great for me.
reset
unset key
bm = 0.15
lm = 0.12
rm = 0.95
gap = 0.03
size = 0.75
y1 = 9.25e+06; y2 = 9.35e+06; y3 = 1.24e+07; y4 = 1.25e+07
set multiplot
set xlabel 'Number of Iterations'
set border 1+2+8
set xtics nomirror
set ytics nomirror
set lmargin at screen lm
set rmargin at screen rm
set bmargin at screen bm
set tmargin at screen bm + size * (abs(y2-y1) / (abs(y2-y1) + abs(y4-y3) ) )
set yrange [y1:y2]
plot 'upquValues.dat' title 'upper quartile', 'MedianValues.dat' using 1 title 'median value', 'loquValues.dat' title 'lower quartile', 'MeanValues.dat' using 1 title 'mean value';
unset xtics
unset xlabel
set border 2+4+8
set bmargin at screen bm + size * (abs(y2-y1) / (abs(y2-y1) + abs(y4-y3) ) ) + gap
set tmargin at screen bm + size + gap
set yrange [y3:y4]
set label 'Runtime [ns]' at screen 0.03, bm + 0.5 * (size + gap) offset 0,-strlen("PRuntime [ns]")/4.0 rotate by 90
set arrow from screen lm - gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1)+abs(y4-y3) ) ) - gap / 4.0 to screen \
lm + gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1) + abs(y4-y3) ) ) + gap / 4.0 nohead
set arrow from screen lm - gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1)+abs(y4-y3) ) ) - gap / 4.0 + gap to screen \
lm + gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1) + abs(y4-y3) ) ) + gap / 4.0 + gap nohead
set arrow from screen rm - gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1)+abs(y4-y3) ) ) - gap / 4.0 to screen \
rm + gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1) + abs(y4-y3) ) ) + gap / 4.0 nohead
set arrow from screen rm - gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1)+abs(y4-y3) ) ) - gap / 4.0 + gap to screen \
rm + gap / 4.0, bm + size * (abs(y2-y1) / (abs(y2-y1) + abs(y4-y3) ) ) + gap / 4.0 + gap nohead
plot 'upquValues.dat' title 'upper quartile', 'MedianValues.dat' using 1 title 'median value', 'loquValues.dat' title 'lower quartile', 'MeanValues.dat' using 1 title 'mean value';
unset multiplot
noises_break
How Can I split it into three parts now? Also the legend and title of the graph does get lost, which I also would like to fix.
My next problem includes saving the graph as png or postscript.
When I first use set term png; set output 'img.png' I generate an empty img.png file. When I plot first and set the term later and use replot only the upper graph is printed.
A simple way to "mimic" two axis breaks is to use set multiplot layout 3,1 and to fix the y-ranges accordingly and to replot your data.
Code:
### two axes breaks
reset session
set colorsequence classic
set key left
set multiplot layout 3,1
set lmargin 5
unset xtics
set border 14
set ytic 1
set yrange [8:10]
plot x, sin(x)*10, -0.3*x**2+10
unset key
set border 10
set yrange [-2:2]
replot
set border 11
set xtics nomirror
set yrange [-10:-8]
replot
unset multiplot
### end of code
Result:
To your other question:
If I use png or pngcairo or postscript terminal, I do:
set term pngcairo
set output 'img.png'
plot x
set output
If I omit the last set output I will get a file 'img.png' with 0 bytes.

Generation of pie chart using gnuplot

I have a CSV file with data like:
name,age
raju,23
anju,34
manju,56
sanju,56
I'm trying to generate a pie chart using gnuplot.
Here's the command I'm executing:
#!/usr/bin/gnuplot -persist
reset
set terminal wxt
unset key
set datafile separator ","
set xlabel "USERS"
set ylabel "AGE"
plot 'file.csv' using ($0):2:($0):xticlabels(1) with circles lc variable notitle
What am I doing wrong?
Apparently, Gnuplot does not support pie charts yet; but we can draw it by hand.
First, we need to obtain the angles and percentages related to the second column in your datafile:
set datafile separator ','
stats 'file.csv' u 2 noout # get STATS_sum (sum of column 2)
ang(x)=x*360.0/STATS_sum # get angle (grades)
perc(x)=x*100.0/STATS_sum # get percentage
Then configure the canvas:
set size square # square canvas
set xrange [-1:1.5]
set yrange [-1.25:1.25]
set style fill solid 1
unset border
unset tics
unset key
and draw the pie chart:
Ai = 0.0; Bi = 0.0; # init angle
mid = 0.0; # mid angle
i = 0; j = 0; # color
yi = 0.0; yi2 = 0.0; # label position
plot 'file.csv' u (0):(0):(1):(Ai):(Ai=Ai+ang($2)):(i=i+1) with circle linecolor var,\
'file.csv' u (1.5):(yi=yi+0.5/STATS_records):($1) w labels,\
'file.csv' u (1.3):(yi2=yi2+0.5/STATS_records):(j=j+1) w p pt 5 ps 2 linecolor var,\
'file.csv' u (mid=Bi+ang($2)*pi/360.0, Bi=2.0*mid-Bi, 0.5*cos(mid)):(0.5*sin(mid)):(sprintf('%.0f (%.1f\%)', $2, perc($2))) w labels
The first line in the plot command draws the pie chart, where the columns (0):(0):(1):(Ai):(Ai=Ai+ang($2)):(i=i+1) are:
columns 1-2: x and y coordinates of the center of the disk
column 3: radius of the disk
column 4-5: begin and end angles of the region
column 6: color of the region
The second and third lines in the plot command place the labels, and the last line puts the percentages in the middle of each region.
The result:
References: (1) Gnuplot surprising (2) Gnuplot tricks
EDIT:
Based on two related questions (this and this), a new script is proposed:
filename = 'test.csv'
rowi = 1
rowf = 7
# obtain sum(column(2)) from rows `rowi` to `rowf`
set datafile separator ','
stats filename u 2 every ::rowi::rowf noout prefix "A"
# rowf should not be greater than length of file
rowf = (rowf-rowi > A_records - 1 ? A_records + rowi - 1 : rowf)
angle(x)=x*360/A_sum
percentage(x)=x*100/A_sum
# circumference dimensions for pie-chart
centerX=0
centerY=0
radius=1
# label positions
yposmin = 0.0
yposmax = 0.95*radius
xpos = 1.5*radius
ypos(i) = yposmax - i*(yposmax-yposmin)/(1.0*rowf-rowi)
#-------------------------------------------------------------------
# now we can configure the canvas
set style fill solid 1 # filled pie-chart
unset key # no automatic labels
unset tics # remove tics
unset border # remove borders; if some label is missing, comment to see what is happening
set size ratio -1 # equal scale length
set xrange [-radius:2*radius] # [-1:2] leaves space for labels
set yrange [-radius:radius] # [-1:1]
#-------------------------------------------------------------------
pos = 0 # init angle
colour = 0 # init colour
# 1st line: plot pie-chart
# 2nd line: draw colored boxes at (xpos):(ypos)
# 3rd line: place labels at (xpos+offset):(ypos)
plot filename u (centerX):(centerY):(radius):(pos):(pos=pos+angle($2)):(colour=colour+1) every ::rowi::rowf w circle lc var,\
for [i=0:rowf-rowi] '+' u (xpos):(ypos(i)) w p pt 5 ps 4 lc i+1,\
for [i=0:rowf-rowi] filename u (xpos):(ypos(i)):(sprintf('%05.2f%% %s', percentage($2), stringcolumn(1))) every ::i+rowi::i+rowi w labels left offset 3,0
This new code results in:

Resources