Gnuplot - How to join smoothly ordered points? - gnuplot

I've a set of data in three columns:
1st column: order criterion between 0 and 1
2nd: x vals
3rd: y vals
As a data file example:
0.027 -29.3 -29.6
0.071 -26.0 -31.0
0.202 -14.0 -32.8
0.304 -3.4 -29.3
0.329 -0.5 -26.0
0.409 6.7 -14.0
0.458 11.7 -3.4
0.471 12.8 -0.5
0.495 12.5 6.7
0.588 18.8 11.7
0.600 20.4 12.8
0.618 20.8 12.5
0.674 20.9 18.8
0.754 22.1 20.4
0.810 27.0 20.8
0.874 24.7 20.9
0.892 9.4 22.1
0.911 -11.5 27.0
0.943 -23.7 24.7
0.962 -29.6 9.4
0.991 -31.0 -11.5
0.999 -32.8 -23.7
My goal is to plot (x,y) points and a trend curve passing through each points ordered in ascending order with the first column values.
I use the following script:
set terminal png small size 600,450
set output "my_data_mcsplines_joined_points.png"
set table "table_interpolation.dat"
plot 'my_data.dat' using 2:3 smooth mcsplines
unset table
plot 'my_data.dat' using 2:3:(sprintf("%'.3f", $1)) with labels point pt 7 offset char 1,1 notitle ,\
"table_interpolation.dat" with lines notitle
Here mcspline results as an example:
mcspline joined points figure
The resulting curve should have the shape of a spindle or a loop.
Whatever smooth options used, Gnuplot seems invalid to handle such aim.
Unfortunatly most of smooth (mcspline, csplines...) options do a monotonic ordering of data.
How can I plot a trend curve passing through each points ordered in ascending order with the first column values?
Thanks.

I cannot post an image in a comment, and so place it here. I don't think a 2D plot will be sufficient, based on this 3D acatterplot of the data in your question.

Related

Gnuplot - How to splot surface and points with dgrid3d

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"

How to plot points with label and color in Gnuplot?

I want to plot points with individual labels and colors in Gnuplot.
I have a data file a.dat:
###label x y z
1 244.8 18 6.1
2 248.0 10.4 7
3 294.4 6.3 13.7
4 248.0 7.5 8.92
5 240.0 3.69 6.61
6 240.48 3.69 8.92
7 256 5.7 15.8
8 256 7 10.6
9 256 4.1 8.2
10 256 5.1 12.3
The following commands work.
splot 'a.dat' using 2:3:4:1 with labels
set palette model RGB defined (0 'black',1 'blue', 2 'green', 3 'red')
splot 'a.dat' using 2:3:4:($1==3?1:$1==6?2:$1==9?3:0) with points palette
But how can I mix them?
Assuming I understood your question correctly, do you really need a palette if you just want to set only a few specific colors to a few specific points?
You are using two plotting styles with points and with labels you can combine them in one plot command.
Code:
### variable color points
reset session
$Data <<EOD
###label x y z
1 244.8 18 6.1
2 248.0 10.4 7
3 294.4 6.3 13.7
4 248.0 7.5 8.92
5 240.0 3.69 6.61
6 240.48 3.69 8.92
7 256 5.7 15.8
8 256 7 10.6
9 256 4.1 8.2
10 256 5.1 12.3
EOD
myColor(col) = column(col)==3 ? 0x0000ff : \
column(col)==6 ? 0x00ff00 : \
column(col)==9 ? 0xff0000 : 0
set key noautotitle
splot $Data u 2:3:4:(myColor(1)) w p pt 7 lc rgb var, \
'' u 2:3:4:1 w labels offset 0.0,0.7,0.7
### end of code
Result:
Addition: (colored labels)
If you want to have colored labels then change the plot command as follows:
splot $Data u 2:3:4:1:(myColor(1)) w labels tc rgb var
Well, you have to decide:
using only labels it might be difficult to locate the exact position of your data point
using a point and a label without offset it might be diffcult to read the number
Result: (colored label without point)

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

PM3d and Impulses combined not scaling

I am new to gnuplot, but I think I have all the basics. I am trying to plot a 3d surface with some impulses. When I do each splot individually, they look great, but when I splot them together, the scale gets all messed up. Any thoughts? Autoscale is set in all cases.
1st splot:
splot "C:/data/file1.dat" matrix rowheaders columnheaders with pm3d
2nd splot:
splot "C:/Data/file2.dat" with impulses, "C:/Data/file2.dat" with points pt 7
Combined:
splot "C:/data/file1.dat" matrix rowheaders columnheaders with pm3d, \
"C:/Data/file2.dat" with impulses, \
"C:/Data/file2.dat" with points pt 7
See how the scale gets all messed up, and the first chart gets scrunched down to one corner? Both data sets have roughly the same ranges in data.
file1.dat
6 8 10 12 16 20 24
30 3.513999939 4.515999794 5.293000221 5.894999981 6.633999825 6.870999813 6.901000023
35 4.235000134 5.330999851 6.169000149 6.72300005 7.196000099 7.374000072 7.434000015
40 4.818999767 5.940999985 6.776000023 7.171000004 7.558000088 7.722000122 7.802999973
45 5.291999817 6.453999996 7.136000156 7.480999947 7.831999779 7.997000217 8.092000008
50 5.656000137 6.791999817 7.393000126 7.718999863 8.057999611 8.232999802 8.340000153
55 5.968999863 7.014999866 7.587999821 7.913000107 8.255000114 8.44299984 8.565999985
60 6.225999832 7.176000118 7.741000175 8.079999924 8.434000015 8.642000198 8.788000107
65 6.414000034 7.326000214 7.859000206 8.225999832 8.602000237 8.840000153 9.015000343
70 6.624000072 7.494999886 7.956999779 8.357000351 8.767000198 9.039999962 9.25
75 6.801000118 7.638999939 8.100999832 8.468000412 8.930000305 9.251999855 9.496999741
80 6.93599987 7.758999825 8.222000122 8.56799984 9.107999802 9.491000175 9.772000313
85 7.035999775 7.855000019 8.322999954 8.690999985 9.289999962 9.748999596 10.10700035
90 7.102000237 7.919000149 8.409999847 8.80300045 9.470999718 10.03199959 10.47500038
95 7.125 7.933000088 8.479000092 8.901000023 9.642999649 10.31599998 10.83600044
100 7.107999802 7.907999992 8.534000397 8.987000465 9.812000275 10.60000038 11.18799973
105 7.053999901 7.849999905 8.515999794 9.06000042 9.972999573 10.86600018 11.52400017
110 6.965000153 7.769999981 8.43500042 9.090999603 10.11800003 11.10400009 11.84200001
115 6.840000153 7.663000107 8.309000015 8.961000443 10.24100018 11.31099987 12.14299965
120 6.672999859 7.524000168 8.149999619 8.75399971 10.32299995 11.48900032 12.42500019
125 6.436999798 7.349999905 7.961999893 8.529000282 9.987000465 11.64599991 12.68999958
130 6.044000149 7.133999825 7.749000072 8.298000336 9.579000473 11.67500019 12.96199989
135 5.572000027 6.856999874 7.513000011 8.06499958 9.237999916 11.11900043 13.27099991
140 5.127999783 6.440000057 7.257999897 7.831999779 8.937999725 10.52499962 12.90999985
145 4.683000088 5.933000088 6.981999874 7.598999977 8.670000076 10.0170002 12.10299969
150 4.30700016 5.52699995 6.657999992 7.363999844 8.425999641 9.602999687 11.39599991
155 3.996999979 5.196000099 6.294000149 7.122000217 8.194000244 9.262000084 10.79100037
160 3.730999947 4.887000084 5.936999798 6.868999958 7.973999977 8.970999718 10.27600002
165 3.506999969 4.620999813 5.642000198 6.610000134 7.78000021 8.737999916 9.892000198
170 3.342999935 4.421999931 5.427999973 6.385000229 7.625 8.56499958 9.626999855
175 3.233999968 4.288000107 5.281000137 6.217000008 7.506999969 8.43900013 9.44299984
180 3.170000076 4.209000111 5.191999912 6.111000061 7.428999901 8.354000092 9.32199955
file2.dat
7.5 172.0 4.5
5.6 56.8 4.7
6.7 35.0 5.1
11.0 158.7 5.3
13.8 24.8 5.6
12.1 180.0 6.0
5.1 83.2 6.4
13.2 158.0 6.6
15.8 34.5 6.67
15.6 32.9 6.69
11.8 180.0 6.8
13.7 96.0 7.2
15.0 62.4 7.3
11.2 76.2 7.3
11.7 84.9 7.4
13.8 121.8 7.46
9.7 90.9 7.6
13.2 66.0 7.64
14.3 61.3 7.8
14.8 124.6 8.0
9.5 118.8 8.20
15.1 148.8 8.29
12.2 81.8 8.4
You can see in your first image that the spacing between x=10 and x=12 is as big as the spacing between x=12 and x=16, which gives a clue to what's going on: while first plot looks like gnuplot is using the x coordinates 8,10,12,16,20,24, those are really only labels, while numerically gnuplot uses the x coordinates 0,1,2,3,4,5,6. So when you then plot the second graph on the same scale, the data points have x values between 5.1 and 15.8, so will show up the side of the pm3d surface.
If you want gnuplot to use the first column and first row as actual coordinates, you have to use the nonuniform matrix format (see help matrix nonuniform). First, you need to change your data file file1.dat to start with the number 7, the number of columns. The beginning of the file should look like this:
7 6 8 10 12 16 20 24
30 3.513999939 4.515999794 5.293000221 5.894999981 6.633999825 6.870999813 6.901000023
35 4.235000134 5.330999851 6.169000149 6.72300005 7.196000099 7.374000072 7.434000015
Then you can plot the data as follows:
splot "file1.dat" nonuniform matrix w pm3d, \
"file2.dat" with impulses, \
"file2.dat" with points pt 7

Best visualization approach to plot a dataset when there is a big difference between the values (GNUPLOT)

I am using the following gnuplot script in order to plot a dataset composed of 400 lines
set title "Learning time for the proposed approachs (Freebase)"
set term png
set boxwidth 3
set style fill solid
set output "dbpedia.png"
set ylabel "Learning time (seconds)"
set xlabel "increasing size of the training dataset"
set xtics font ", 9"
set grid
everyfifth(col) = (int(column(col))%10 ==0)?stringcolumn(1):""
plot for [col=2:4] "dbpedia_duration.txt" every 10 using col:xticlabels(everyfifth(0)) with lines lw 2 title columnheader
Sample dataset
size DDS-rand DDS-ambig DDS-ambig-NN
10 0.003 0.01 0.046
20 0.004 0.423 2.094
30 0.004 1.768 9.262
40 0.004 5.933 30.649
50 0.003 0.586 2.871
60 0.007 2.282 14.226
70 0.005 0.512 2.707
80 0.007 0.089 0.468
90 0.006 4.61 24.471
100 0.006 3.013 16.411
110 0.006 1.578 8.244
120 0.006 1.194 6.418
130 0.008 2.401 12.398
140 0.008 0.014 0.027
150 0.007 0.284 1.541
160 0.009 1.25 7.598
170 0.012 2.027 11.149
Problem and questions
As you can see there is a big difference between the blue curve on one side and the red and green curves on the other side. It's hard to see the other curves on a black and white paper.
Is there a better way to plot this dataset? It is really annoying because we can barely see the red and green curves.
update
if we use the set logscale y as suggested by #Daniel we do get a clear graph.
A standard approach would be to plot the y axis logarithmically, such that the tics for 0.001, 0.01, 0.1, 1, 10, ... are equidistant.
set logscale y
Note: this does not work if your data set contains values exactly equal to zero. In this case, you could use
plot 'data.txt' using 1:($2>0? $2 : 1/0)
to skip values with y == zero (1/0 = undefined, which will be skipped by gnuplot). Adjust column numbers for x and y for your data file.

Resources