Gnuplot - How to splot surface and points with dgrid3d - gnuplot

I have a .dat file that I need to plot as a surface :
functionVisu.dat
X Y Z
0 -3.9 1.68777
0 -4 1.7568
0 -4.1 1.81828
0 -4.2 1.87158
0 -4.3 1.91617
0 -4.4 1.9516
0 -4.5 1.97753
0 -4.6 1.99369
0 -4.7 1.99992
0 -4.8 1.99616
0 -4.9 1.98245
-0.1 -3.9 1.68277
-0.1 -4 1.75181
-0.1 -4.1 1.81328
-0.1 -4.2 1.86658
-0.1 -4.3 1.91117
-0.1 -4.4 1.94661
-0.1 -4.5 1.97253
-0.1 -4.6 1.9887
-0.1 -4.7 1.99493
-0.1 -4.8 1.99117
-0.1 -4.9 1.97746
-0.2 -3.9 1.66783
-0.2 -4 1.73687
etc
But also need to plot points on this surface, the file containing the points (pointVisu.dat) is also XYZ values.
The problem is, with my actual script:
set hidden3d
set dgrid3d 50,50 qnorm 2
splot [-10:10][-10:10] "functionVisu.dat" with lines, "pointVisu.dat" with dots lw 10 lc rgb "red"
pause -1
the result I am getting is not looking as expected :
result
My points are spreaded due to the dgrid3d, but I can't manage to make them appear as wanted. Also, with the use of qnorm 2, the points are under the surface function even though they are strict images of it.
Points under the surface
I can have the result I want but without using dgrid3d, which gives me a good but not aesthetic result:
Wanted but bad result
How could I combinate the render of dgrid3d but with single points displaying properly ?
Thanks

Gnuplot version 5.4.3 (Dec 2021) introduced a keyword "nogrid" that can be added to the splot command so that points are plotted individually rather being used for a grid. So if your copy of gnuplot is new enough, the answer to one of your questions is shown below (using some other data)
set hidden3d
set dgrid3d 25,25
splot "foo.dat" with lines title "gridded", \
"foo.dat" with points nogrid pt 7 title "nogrid"
Fallback for older gnuplot versions
For older gnuplot versions that do not recognize the nogrid keyword there is a work-around. Not all plot styles can be gridded, and this includes the with labels plot style. But labels can have an associated point, so you can plot a set of non-gridded points by describing them as labels with blank text:
splot "foo.dat" using 1:2:3 with lines title "gridded", \
"foo.dat" using 1:2:3:("") with labels point pt 7 title "nogrid"

Related

Gnuplot: How to draw an opposing bar plot or pyramid bar diagram

Is it possible to use two positive y-axes with gnuplot? This is just a simple example for the question.
plot.gp:
reset
set style fill solid 1
set boxwidth 0.8 relative
plot 'data1.dat' index 1 using 1:2 with boxes title 'A' ,\
'' index 2 using 1:(-$2) with boxes title 'B'
Instead of using 1:(-$2) I would like to use 1:2 in the last line in plot.gp.
data1.dat:
0.12 0.024
0.15 0.132
0.18 0.241
0.22 0.136
0.12 0.039
0.15 0.219
0.18 0.197
0.22 0.155
From:
To:
Same answer as the one from theoz except that the y2 labels are shifted to the left side of the plot and the set link y2 command is used to generalize the axis inversion.
You can tweak the offset graph -1.03 to superimpose the "0" labels, then delete the duplicate "0" label by changing the y2 tic range to set y2tics 0.1,0.1.
$Data <<EOD
0.12 0.024
0.15 0.132
0.18 0.241
0.22 0.136
0.12 0.039
0.15 0.219
0.18 0.197
0.22 0.155
EOD
set style fill transparent solid 0.5
set boxwidth 0.8 relative
set xzeroaxis ls -1
set yrange[-0.3:0.3]
set ytics 0,0.1
set mytics 2
# Set y2 axis to exact mirror of y1
# Shift tic labels to the left and use right-justified text
set link y2 via -y inv -y
set y2tics 0,0.1
set y2tics offset graph -1.03 right
plot $Data u 1:2 index 0 axis x1y1 w boxes title 'A' ,\
'' u 1:2 index 1 axis x1y2 w boxes title 'B'
Here is a solution with a single plot, however, the y-axis tics are on different sides.
Maybe there is some easy way to get them on the same side.
Code:
### two "positive" y-axes
reset session
$Data <<EOD
0.12 0.024
0.15 0.132
0.18 0.241
0.22 0.136
0.12 0.039
0.15 0.219
0.18 0.197
0.22 0.155
EOD
set style fill transparent solid 0.5
set boxwidth 0.8 relative
set yrange[-0.3:0.3]
set ytics 0,0.1
set mytics 2
set y2range[0.3:-0.3]
set y2tics 0,0.1
set my2tics 2
set y2tics mirror
set xzeroaxis ls -1
plot $Data u 1:2 index 0 axis x1y1 w boxes title 'A' ,\
'' u 1:2 index 1 axis x1y2 w boxes title 'B'
### end of code
Result:
Addition:
Here is a second suggestion with all ytic labels on one side.
A little drawback is that it is not autoscale and you have to set the range and the steps "manually".
It is using the command evaluate (check help evaluate). And real() (check help real) in order to avoid gnuplot's integer division in case the two numbers of the division might be integers.
Code:
### y-axis with two "positive" directions
reset session
$Data <<EOD
0.12 0.024
0.15 0.132
0.18 0.241
0.22 0.136
0.12 0.039
0.15 0.219
0.18 0.197
0.22 0.155
EOD
set style fill transparent solid 0.5
set boxwidth 0.8 relative
set xzeroaxis ls -1
Max = 0.3
Steps = 3
set yrange[-Max:Max]
set ytics () # remove all tics
do for [i=-Steps:Steps] {
myTic = sprintf('set ytics add ("%g" %g)',abs(real(i)/Steps*Max),real(i)/Steps*Max)
eval(myTic)
}
plot $Data u 1:2 index 0 axis x1y1 w boxes lc 3 title 'A' ,\
'' u 1:(-$2) index 1 axis x1y1 w boxes lc 4 title 'B'
### end of code
Result:

Plot a error bar as shaded region in GNUPLOT

I have plotted a graph (X-top axis, Y-bottom axis) with fsteps function in Gnuplot. Next, I tried to add an error bar as a shaded region(transparent) to the graph, but unable to plot it on the graph. Below is the code so far I have tried and also attached the graph.
#!/usr/bin/gnuplot
reset
set border lw 30
set term pngcairo size 10000,10000 font "arial-Bold,130"
set output 'out.png'
unset key
set size ratio 1.2
set style data lines
set xtics format ""
set x2tics nomirror
set ytics out nomirror
set ytics 0,20
set x2label "Vs (km/s)" offset -1.0
set ylabel 'Depth (km)' offset 1.5
set xrange [2.5:4.8]
set yrange [314:0]
set label 3 at 2,120
set key samplen 1.7 at 3.0,135
#
set label 1 '(a)' font "arial-Bold,130" at 0.8,15 right
set label 3 "C3 (MNAI)" center font "arial-Bold,130"
set style fill transparent solid 0.25
set style fill noborder
plot 'MAN.inmd' lc rgb 'blue' lw 35 title "Initial model" with fsteps,\
'MAN.outmd' using 1:2 lc rgb 'red' lw 35 dt"-" title "Inverted model" with fsteps ,\
'MAN.outmd' using 1:($2-$3):($2+$3) with filledcurve lc "blue" notitle,
Example Data for file MAN.outmd X Y Z(Error)
0 3 0
0.4475 3.1 0
0.4475 3.5 0
2.6738 3.6 0.0552
2.6738 5 0.0552
3.8441 5.1 0.0592
3.8441 8 0.0592
3.6302 8.1 0.0395
3.6302 15.935 0.0395
4.5176 15.1 0.041
4.5176 113.296 0.041
4.2443 113.3 0.1024
4.2443 214 0.1024
4.4584 214.1 0.1077
4.4584 314 0.1077
I want output should be as given below (example)
gnuplot can easily fill the area between two "horizontal" curves (i.e. unique x-values), but as far as I know, not between two vertical curves. However, gnuplot can fill some enclosed areas. So, the workaround is to create datapoints which surround the area to be shaded. For this, you "plot" the data into a datablock, once "forward" with x-dx and once "backwards" with x+dx. This can be done easiest if you have the data already in a datablock, because then you can easily loop the data forward and backwards. In case you have your data in a file, see here: gnuplot: load datafile 1:1 into datablock
Code:
### fill between vertical curves
reset session
$Data <<EOD
0 3 0
0.4475 3.1 0
0.4475 3.5 0
2.6738 3.6 0.0552
2.6738 5 0.0552
3.8441 5.1 0.0592
3.8441 8 0.0592
3.6302 8.1 0.0395
3.6302 15.935 0.0395
4.5176 15.1 0.041
4.5176 113.296 0.041
4.2443 113.3 0.1024
4.2443 214 0.1024
4.4584 214.1 0.1077
4.4584 314 0.1077
EOD
# create datablock with circumference of shaded area
set print $XErrorFill
do for [i=1:|$Data|] {
print real(word($Data[i],1))-real(word($Data[i],3)), real(word($Data[i],2))
}
do for [i=|$Data|:1:-1] {
print real(word($Data[i],1))+real(word($Data[i],3)), real(word($Data[i],2))
}
set print
set yrange [:] reverse
set style fill noborder
plot $XErrorFill u 1:2 w filledcurves lc "light-grey" notitle, \
$Data u 1:2 w l lw 1.5 lc rgb "red" notitle
### end of code
Result:

How to use set offset for only 1 of the datasources in gnuplot?

I want to plot two datasources together in gnuplot: one from a datafile, using text as x-data (with xticlabels and errorbars) and another a constant.
I don't want the xticlabels to reach the sides of the graph, so I use "set offset". However, I do want the constant to reach the sides of the graph.
An example gnuplot script:
set terminal pngcairo size 500, 500
file = 'data.txt'
set output 'plot.png'
set xtics rotate by -45
set yrange [0:1]
set offset 0.5,0.5,0,0
plot file using 0:2:3:xticlabels(1) with yerrorbars notitle,\
0.5 notitle
With the associated data.txt file:
"Europe" 0.4 0.03
"North America" 0.8 0.05
"South America" 0.1 0.08
"Asia" 0.7 0.01
"Africa" 0.9 0.03
"Australia" 0.2 0.03
Provides the following plot:
However, I want the following plot:
How can I achieve this?
You can achieve the same result if you are simply setting the xrange[] properly.
In your case when using xticlabels(1), Europe=0 and Australia=5.
So, simply set xrange[-0.5:5.5]. If the number of items (here 6) is unknown beforehand you could get it either via |$Data| or stats $Data and STATS_records.
Code:
### border when using xticlabels()
reset session
$Data <<EOD
"Europe" 0.4 0.03
"North America" 0.8 0.05
"South America" 0.1 0.08
"Asia" 0.7 0.01
"Africa" 0.9 0.03
"Australia" 0.2 0.03
EOD
set xtics rotate by -45
set xrange [-0.5:5.5]
set yrange [0:1]
plot $Data using 0:2:3:xticlabels(1) with yerrorbars notitle,\
0.5 notitle
### end of code
Result:
You could draw the constant as headless arrow:
set arrow from graph 0, first 0.5 to graph 1, first 0.5 nohead lt 1

Display changing column value in Gnuplot animation

I am making a gnuplot animation of a satellite going around a planet. My task is to display it's XY trajectory and associated values of velocity and energy versus time. I know how to plot the path, but I've been having problems displaying velocity etc.
the code below does the following:
satellite track and time steps -- column 3:4;
satellite position -- column 3:4;
planet position -- column 6:7.
do for [n=0:int(STATS_records)] {
plot "sat.dat" u 3:4 every ::0::n w lp ls 2 t sprintf("steps=%i", n), \
"sat.dat" u 3:4 every ::n::n w lp ls 4 notitle, \
"sat.dat" u 6:7 every ::0::n w lp ls 3 notitle , \
}
How do I display the associated velocity values for each sprintf ? The velocity values are in column 5. Thank you everyone in advance.
It seems that you want to put everything in the "key" (legend), but another option is to use labels, which can be easily placed arbitrarily. There are labels you can place one at a time (with set label) and with labels for plotting with actual labels. Don't get them confused.
Your main issue seems to be how to pull out the velocity value from column 5. My first instinct (which is quite hacky) is to use some external program, like awk:
v = system(sprintf("awk 'NR==%d{print $5}' '%s'", n+1, infile))
set label 1 sprintf("v=%.3f", v+0) at screen 0.2,0.9
This is also an example of a label (named 1). The screen keyword means screen-relative rather than graph-relative. Putting this inside your for loop will reassign label 1 every iteration, so it overwrites the label from the previous iteration. Not using this 1 will just plop another label on top of the last one, so it would get messy.
Using an external command line like this isn't very portable. (I don't think it would work on Windows.) I saw this question that shows how to pull a value from a specific row and column of a file. The problem I had with using this is that stats implicitly filters according to whatever xrange is set. When making animations like this, I've noticed that the camera can jump around too much from autoranging, so it's nice to have tight control over the plotting range. Defining an xrange at the top of the file interfered with a subsequent stats command to read a velocity value.
You can, however, specify a range for stats (before the file name, such as stats [*:*] infile). But I had issues using this in combination with a predefined xrange based for position. I found that it did work if I specify the desired plotting range on the plot line instead of a set xrange. Here is another (full script) version using only gnuplot:
set terminal pngcairo
infile = 'anim.dat'
stats infile using 3:4 name 'data' nooutput
set key font 'Courier'
do for [n=0:data_records-1] {
set output sprintf('frame-%03d.png', n)
stats [*:*] infile every ::n::n using 5 name 'velocity' nooutput
plot [data_min_x:1.1*data_max_x][data_min_y:1.1*data_max_y] \
infile u 3:4 every ::0::n w linespoints ls 2 t \
sprintf("steps =%6d\nvelocity =%6.3f", n, velocity_min), \
'' u 3:4 every ::n::n w points pt 7 ps 3 notitle
}
Notice that you could easily change this to a set label if you want. Another option is to plot
'' u (x):(y):5 every ::n::n w labels
to place a label at graph position (x,y).
I don't have your data, but I made my own file with what I hope is a similar format to yours:
anim.dat
0 0.0 0.0 0.0 1.11803398875 0.625
1 0.05 0.05 0.02375 1.09658560997 0.625
2 0.1 0.1 0.045 1.07703296143 0.625
3 0.15 0.15 0.06375 1.05948100502 0.625
4 0.2 0.2 0.08 1.04403065089 0.625
5 0.25 0.25 0.09375 1.0307764064 0.625
6 0.3 0.3 0.105 1.01980390272 0.625
7 0.35 0.35 0.11375 1.01118742081 0.625
8 0.4 0.4 0.12 1.00498756211 0.625
9 0.45 0.45 0.12375 1.00124921973 0.625
10 0.5 0.5 0.125 1.0 0.625
11 0.55 0.55 0.12375 1.00124921973 0.625
12 0.6 0.6 0.12 1.00498756211 0.625
13 0.65 0.65 0.11375 1.01118742081 0.625
14 0.7 0.7 0.105 1.01980390272 0.625
15 0.75 0.75 0.09375 1.0307764064 0.625
16 0.8 0.8 0.08 1.04403065089 0.625
17 0.85 0.85 0.06375 1.05948100502 0.625
18 0.9 0.9 0.045 1.07703296143 0.625
19 0.95 0.95 0.02375 1.09658560997 0.625

merging multiple data files to plot in a single graph

extending the question I had asked earlier which can be found here, plotting multiple (x,y) co-ordinates in a single curve with gnuplot. I am trying to plot the bezier curves in gnuplot using 2 different files. Each (x,y) from the first file forms a bezier curve passing through the points from the second file. The first file has the co-ordinates like the following:
x y
0.0 0.5
0.12 0.1
0.16 0.4
0.2 0.35
0.31 0.8
0.34 0.6
0.38 1.0
0.46 0.2
0.51 0.7
0.69 0.9
The second file has the co-ordinates as the following:
x y
0.00 0.7
0.04 0.74073082208
0.08 0.85926917792
0.12 0.9
0.16 0.9
0.2 0.9
0.24 0.749720623086
0.28 0.874229601255
0.32 0.74073082208
0.36 0.8
0.4 0.721178508605
0.44 0.878821491395
0.48 0.761772990545
0.52 0.700774803388
0.56 0.723771273415
0.6 0.789508073675
0.64 0.864014272269
0.68 0.896743348931
Now, how do I merge these two files to plot a single graph. These two files don't have the same number of rows, but I guess that doesn't matter. The first curve would be between (x1,y1) and (x2,y2) from the first file which would continue till (x10,y10). In the curve between (x1,y1) and (x2,y2); the points (x1,y1), (x2,y2) and (x3,y3) from the second file lie.
I followed this link http://t16web.lanl.gov/Kawano/gnuplot/datafile3-e.html to sort and concatenate the two files but got some weird lines which is totally wrong. These values should actually plot Bezier curves but not getting the graph. I have written the following gnuplot script to plot the concatenated data:
set term x11 persist
set title "Animation curves"
set xlabel "Time (secs.)"
set ylabel "Parameter"
set x2label "Phoneme1" offset -35
set pointsize 2
set key off
set style line 2 lt 0 lc 1 lw 2
set xrange [0.0:1.0]
set yrange [0.0:1.3]
plot [0.0:0.8] "< cat -n file1.dat" u 1:2 smooth csplines ls 1, "" u 1:(0.0):(0):(1.3) w vectors nohead ls 2, "" u ($1+0.005):(1):(sprintf("P %d", $0)) w labels, \
"file1.dat" u 1:2 with points, \
"file2.dat" u 1:2 with points, \
I got the following error:
plot "< cat -n file1.dat" u 1:2 smooth csplines ls 1, "" u 1:(0.0):(0):(1.3) w vectors nohead ls 2, "" u ($1+0.005):(1):(sprintf("P %d", $0)) w labels, "file1.dat" u 1:2 with points, "file2.dat" u 1:2 with points,
^
"plot.gp", line 21: Cannot smooth: no data within fixed xrange!
The script below works on my machine. Maybe this is even what you are looking for...
set term x11 persist
set title "Animation curves"
set xlabel "Time (secs.)"
set ylabel "Parameter"
set x2label "Phoneme1" offset -35
set pointsize 2
set key off
set style line 2 lt 0 lc 1 lw 2
set xrange [0.0:1.0]
set yrange [0.0:1.3]
plot [0.0:0.8] "< cat file1.dat file2.dat | sort -n" u 1:2 smooth csplines ls 1, \
"" u 1:(0):(0):2 w vectors nohead ls 2, \
"" u ($1 + 0.005):(1):(sprintf("P %d", $0)) w labels, \
"file1.dat" u 1:2 w p, \
"file2.dat" u 1:2 w p

Resources