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"
}
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)
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.
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.
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: