Gnuplot cspline interpolation dataset at specified points - gnuplot

I have two files,
say file 1
x y
0.0 1.0
1.0 2.0
3.0 5.0
and file 2
x
0.5
1.815
2.5
I want to get smooth cspline interpolation values of file 1, but on the x-axis as specified by file 2.
I know how we can set the table and sample size and get the output determined by sample size, but i want to have data points value at the points specified by second file. Is there a way to do it?

Suppose you have a file named data.dat containing this:
# x y
0.000 0.007
1.111 0.013
2.222 0.061
3.333 0.164
4.444 0.250
5.556 0.273
6.667 0.158
7.778 0.061
8.889 0.015
10.000 0.018
You know that this data are described by Gaussian function.
On gnuplot it can been written as:
g(x) = a*exp(-(x - b)**2/2*c**2)
Suppose yet you have another file named x-values.dat containing
the values which you want interpolate.
# x
0.923
1.497
2.357
3.900
4.396
5.696
6.658
7.146
8.851
9.947
You can use fit command to find a, b, and c values which fits data.
At last you use the x-values.dat as input to Gaussian function.
# The Gaussian function
g(x) = a*exp(-(x - b)**2/2*c**2)
# Initial values
a = 0.5 # Height of the curve's peak
b = 6.0 # Position of the center of the peak
c = 1.0 # Controls the width of the "bell"
set fit prescale # Helps to fit if there are parameters that
# differ in size by many orders of magnitude
# Performs the fit
fit g(x) 'data.dat' u 1:2 via a, b, c
# The graph itself:
# 1: Data points
# 2: Gaussian function after fit
# 3: Gaussian function using values from 'x_values.dat' as input
plot \
'data.dat' u 1:2 w p pt 5 lc 'black' t 'Data',\
g(x) w l lc 'red' t 'Gaussian',\
'x_values.dat' u 1:(g($1)) w p pt 7 lc 'blue' t 'Interpolation'

Related

Combining yerrorbars and variable point size

I'm trying to plot the following data file
#x y s err
1 1 0.1 0.2
2 2 0.2 0.2
3 3 0.3 0.2
4 4 0.4 0.2
5 5 0.5 0.2
6 6 0.6 0.2
7 7 0.7 0.2
8 8 0.8 0.2
9 9 0.9 0.2
10 10 1.0 0.2
where the points have a variable size given by column 3 and the errors are given in column 4. I can get
plot "test" u 1:2:3 pt 7 ps variable
plot "test" u 1:2:4 w yerrorbars pt 7
to work independently, giving me this:
But when I try to combine them
plot "test" u 1:2:4:3 w yerrorbars pt 7 ps variable
I get something very strange:
yerrorbars seems to be using column 4 as the y column and column 3 as the yerror column. Even stranger, I get the same output if I try u 1:2:3:4. Is there something wrong with how I'm doing this? I can manually draw the errorbars as vectors, but I'd prefer to use the built-in errorbars style if possible.
gnuplot> help yerrorbars
The `yerrorbars` (or `errorbars`) style is only relevant to 2D data plots.
`yerrorbars` is like `points`, except that a vertical error bar is also drawn.
At each point (x,y), a line is drawn from (x,y-ydelta) to (x,y+ydelta) or
from (x,ylow) to (x,yhigh), depending on how many data columns are provided.
The appearance of the tic mark at the ends of the bar is controlled by
`set errorbars`.
2 columns: [implicit x] y ydelta
3 columns: x y ydelta
4 columns: x y ylow yhigh
An additional input column (4th or 5th) may be used to provide information
such as variable point color.
So in order to provide more than 3 columns and still use a single value for the ydelta, you should be able to do
plot "test" u 1:2:($2-$4):($2+$4):3 w yerrorbars pt 7 ps variable
However, as you point out this doesn't actually work as documented.
Work-around
An alternative is to make two passes; first plot the errorbar lines and suppress the points, second plot the point with the desired properties :
unset key
plot "test" u 1:2:3 with yerrorbars pt 0, \
"" u 1:2:4 with points pt 7 ps variable

Gnuplot pull function range from a file for each row

I am trying to display a function which is a linear function f(x)=a*x+b with different coefficients in each range. My file (output.txt) looks like this but without the header:
a b range
-0.0645991 0.439102 0 0.25
-0.230142 0.480488 0.25 0.5
-0.438559 0.584697 0.5 0.75
-0.66962 0.757993 0.75 1
-0.898603 0.986975 1 1.25
-1.09846 1.2368 1.25 1.5
-1.24232 1.45259 1.5 1.75
-1.30601 1.56404 1.75 2
I have tried these lines but none of them worked:
plot "output.txt" using 1:2 with lines, set xrange using 3:4
plot "output.txt" [($3):($4)] ($1)*x+($2)
plot "output.txt" $3<=x<=$4 ? ($1)*x+($2) : 0
It's my first time using Gnuplot and I couldn't find any example of pulling range from a file.
Welcome to StackOverflow! You can simply use the plotting style with vectors.
Check help vectors.
The plotting command looks complicated but it is straightforward.
The four values you need are: x, y, delta x, and delta y, i.e.
in your example
x: 3rd column
y: f(x,a,b) where x is 3rd column and a and b are from 1st and 2nd columns, respectively.
dx: 4th column less 3rd column
dy: f(x,a,b) where x is from 4th column less f(x,a,b) where x is from 3rd column and a,b as above.
You can skip the arrow heads if you specify nohead in the plot command. Check help arrow.
Code:
### plotting style with vectors
reset session
$Data <<EOD
a b range
-0.0645991 0.439102 0 0.25
-0.230142 0.480488 0.25 0.5
-0.438559 0.584697 0.5 0.75
-0.66962 0.757993 0.75 1
-0.898603 0.986975 1 1.25
-1.09846 1.2368 1.25 1.5
-1.24232 1.45259 1.5 1.75
-1.30601 1.56404 1.75 2
EOD
f(x,a,b) = a*x + b
plot $Data u 3:(f($3,$1,$2)):($4-$3):(f($4,$1,$2)-f($3,$1,$2)) w vectors lc "red" head title "my function"
### end of code
Result:

Drawing a simple polygon using Gnuplot with "angle signs"

Disclaimer: I am new to Gnuplot, and I need to plot some "simple" things for my studies.
I want to plot a part of a polygon with some names and vectors added.
The picutre below was created with Euklid Dynageo, and I am now trying to create this with Gnuplot.
The biggest problem I am facing right now is the labeling u,v,w and adding the angles to the plot. I think I would use vectors and lines.
Do you now a 'simple' way to create this plot?
If you really need to use Gnuplot for this, you have to make it all manually by placing various objects, labels and arrows (keep in mind that complex plots will be cumbersome). A minimal example for two arrows and alpha_1, similar like in your example, could like like this:
# two arrows:
set arrow 1 from 0,0 to sqrt(2)/2,sqrt(2)/2
set arrow 2 from 0,0 to 1,0
# the alpha_1 symbol:
set label 1 '{/Symbol a}_1' at 0.2,0.1 front
# the filled yellow arc (from 0 to 45deg):
set style fill solid 1.0 border
set object 1 circle at 0,0 radius 0.2 arc[0:45] fc rgb "yellow"
# proper ratio, range, and plot 'something':
set xrange[-0.1:1.1]
set yrange[-0.1:1.1]
set size ratio 1
plot 1/0
Lookup the manual for possible object properties.
gnuplot is a very versatile plotting tool, but certainly not optimized for such tasks. For this type of drawing maybe Inkscape or others tools might be better choices, especially for interactive drawing by clicking, dragging and snapping.
And as #JackGlasshard already mentioned, of course you can do such graphs with gnuplot which will be rather time consuming if you do it manually.
Alternatively, you can facilitate the work if you use a "template".
Creating such a template probably only makes sense if you need to create more than one drawing.
Just for fun and feasibility, I tried to create such a template for general use to make such graphs easier.
For the input data you need 3 datablocks (without headers)
$Points: # no., x, y, label, xoff, yoff, pt, ps, color
you define: point number, x-coordinate, y-coordinate, point label, x-offset, y-offset, pointtype, pointsize, point color
$Vectors: # p1, p2, label, arrow, lw, dt, xoff, yoff, color
you define: first point number, second point number, label, arrowsstyle (-1=backhead, 0=nohead, 1=head, 2=heads), linewidth, dashtype, x-offset, y-offset, vector color
$Angles: # p1, p2, p3, r, label, aoff, roff, color
you define: 1st point number, 2nd point number (=angle center point), 3rd point number, radius, label, angular label offset, radial label offset, color
Now, you only have to change the data part of the script for your custom graph. In case you want to insert "invisible" vector starting or end points, simply set pointsize to 0 in $Points. The plotting of the variable arrowheads is a bit cumbersome because of the issue mentioned in this question.
For sure, more features and more flexibility can be added to the template. No warranty that the script is free of bugs. There is certainly room for improvements.
Update: (linewidth and dashtype added)
Since there is no variable linewidth (lw var) and no variable dashtype (dt var)
you have to plot each line separately in a for loop and every ::n::n.
Furthermore, I noticed that the order of variable pointsize (ps var) and and variable pointtype (pt var) apparently has changed from gnuplot 5.2 to 5.4. Not sure whether this intentional or a "bug".
The version below has the order for gnuplot 5.4.
Script:
### drawing sketch with points, vectors and angles
reset session
# no., x, y, label, xoff, yoff, pt, ps, color
$Points <<EOD
1 1 1 "" 0 0 5 1 0xff0000
2 10 2 V_{i-1} 0 0 5 1 0xff0000
3 15 10 V_i 0 0 5 1 0xff0000
4 4 12 X -1.5 0 5 1 0xff0000
5 14 16 V_{i+1} 0 0 5 1 0xff0000
6 5 20 "" 0 0 5 1 0xff0000
EOD
# p1, p2, label, arrow, lw, dt, xoff, yoff, color
# arrows: -1=backhead, 0=nohead, 1=head, 2=heads
$Vectors <<EOD
1 2 "" 0 1.0 1 0 0 0xff0000
2 3 "" 0 2.0 1 0 0 0x000000
3 5 "" 0 1.5 3 0 0 0x000000
4 2 w 1 1.0 1 1.0 0 0x000000
4 3 v 1 1.0 1 0 0.7 0x0000ff
4 5 u 1 1.0 1 0 0.7 0x000000
5 6 "" 0 1.0 1 0 0 0x000000
EOD
# p1, p2, p3, r, label, aoff, roff, color
# p2=angle center point
$Angles <<EOD
2 4 3 4.0 α_{i-1} 7.0 0.5 0xffcccc
3 4 5 4.5 α_i 3.0 0.7 0xffffcc
EOD
### end of data input
### start of template
# point/vector coordinates
px(n,m) = real(word($Points[int(word($Vectors[n],m))],2)) # x coordinate of point n
py(n,m) = real(word($Points[int(word($Vectors[n],m))],3)) # y coordinate of point n
vxd(n) = px(n,2)-px(n,1) # vector delta x
vyd(n) = py(n,2)-py(n,1) # vector delta y
vxc(n) = (px(n,2)+px(n,1))/2. # vector center x
vyc(n) = (py(n,2)+py(n,1))/2. # vector center y
lw(n) = real(word($Vectors[n],5))
dt(n) = int(word($Vectors[n],6))
# angles
as(n) = int(column(5)+2) # arrow style
ax(n) = real(word($Points[int(word($Angles[int(column(0)+1)],n))],2)) # angle center x
ay(n) = real(word($Points[int(word($Angles[int(column(0)+1)],n))],3)) # angle center y
set angle degrees
Angle(x0,y0,x1,y1) = (_dx=x1-x0, _dy=y1-y0, _L=sqrt(_dx**2 + _dy**2), _L==0 ? NaN : \
(_dy>=0 ? acos(_dx/_L) : -acos(_dx/_L) ))
a1(m) = Angle(ax(2),ay(2),ax(1),ay(1)) # starting angle
a2(m) = Angle(ax(2),ay(2),ax(3),ay(3)) # end angle
set style arrow 1 backhead filled # -1
set style arrow 2 nohead filled # 0
set style arrow 3 head filled # 1
set style arrow 4 heads filled # 2
set size ratio -1 # ensure same x- and y-ratio
set key noautotitle
set xrange [0:22]
set yrange [0:22]
set mxtics 5
set mytics 5
set grid x,y,mx,my
set style fill solid 0.5 border lc "black"
plot $Angles u (ax(2)):(ay(2)):4:(a1(0)):(a2(0)):8 w circles lc rgb var, \
'' u (ax(2)+($4*0.5+$7)*cos(0.5*(a1(0)+a2(0))+$6)): \
(ay(2)+($4*0.5+$7)*sin(0.5*(a1(0)+a2(0))+$6)):5 w labels font "Times New Roman,13" center, \
for [i=1:|$Vectors|] $Vectors \
u (px(i,1)):(py(i,1)):(vxd(i)):($4==-1?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled backhead, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 0?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled nohead, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 1?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled head, \
for [i=1:|$Vectors|] '' \
u (px(i,1)):(py(i,1)):(vxd(i)):($4== 2?vyd(i):NaN):9 every ::i-1::i-1 w vectors lc rgb var lw lw(i) dt dt(i) filled heads, \
for [i=1:|$Vectors|] '' \
u (vxc(i)+$7):(vyc(i)+$8):3:9 every ::i-1::i-1 w labels font ",12" tc rgb var, \
$Points u 2:3:7:8:9 w p ps var pt var lc rgb var, \
'' u ($2+$5):($3+$6):4:9 w labels tc rgb var font ",12" left offset 1,0
### end of script
Result:

Gnuplot: Find y value for given x value

I have a set of data points I plot with gnuplot. Know I calculate a value for x and want to find the corresponding y value within the data.
Does anybody know how to manage this with gnuplot?
I found kind of a solution here on StackOverflow
Basically you have to invert the function you use to calculate y (or x in the case of the link) and then, thanks to the sprintf function, you gate the corresponding value.
NOTE
Have a look also here if you did not find the solution at the first link!
Although this is a rather old question, the following solution for interpolation might still be of interest to others.
The code can be simplified depending on whether you are just interested in nearest datapoint or in the interpolated value or whether you want to plot the value as point and/or label.
Code:
### interpolate between datapoints
reset session
$Data <<EOD
0 0
0.30 0.20
0.60 0.40
0.80 0.80
1 1
EOD
$Data2 <<EOD
1 0
0.80 0.15
0.50 0.30
0.50 0.50
0.30 0.80
0 1
EOD
InterpolY(x,x0,x1,y0,y1) = (x-x0)*(x-x1)<0 || x1-x0==0 ? x1-x0==0 ? (y0+y1)/2 : (y1-y0)/(x1-x0)*(x-x0) +y0 : NaN
set key noautotitle
array Point[1] # dummy array for plotting a single datapoint
# x-value for interpolation is defined in xp
plot x1=y1=yp=(xp=0.7,NaN) $Data u (x0=x1,x1=$1):(y0=y1,y1=$2, yp==yp ? NaN : yp=InterpolY(xp,x0,x1,y0,y1),y1) w lp pt 7, \
Point u (xp):(yp) w p pt 7 lc "red", \
Point u (xp):(yp):(sprintf("(%.2g|%.2g)",xp,yp)) w labels right offset -1,0 lc "red", \
x1=y1=yp=(xp=0.5,NaN) $Data2 u (x0=x1,x1=$1):(y0=y1,y1=$2, yp==yp ? NaN : yp=InterpolY(xp,x0,x1,y0,y1),y1) w lp pt 7, \
Point u (xp):(yp) w p pt 7 lc "green", \
Point u (xp):(yp):(sprintf("(%.2g|%.2g)",xp,yp)) w labels right offset -1,0 lc "green", \
### end of code
Result: (interpolated values at x=0.7 and x=0.5)

Gnuplot: plotting points with variable point types

I have x,y values for points in the first 2 colums and a number that indicates the point type (symbol) in the 3. column, in one data file. How do I plot data points with different symbols?
Unfortunately, there isn't a way (AFAIK) to automatically set the point of the plot from a column value using vanilla GNUPLOT.
However, there is a way to get around that by setting a linestyle for each data series, and then plotting the values based on that defined style:
set style line 1 lc rgb 'red' pt 7 #Circle
set style line 2 lc rgb 'blue' pt 5 #Square
Remember that the number after pt is the point-type.
Then, all you have to do is plot (assuming that the data in "data.txt" is ordered ColX ColY Col3):
plot "data.txt" using 1:2 title 'Y Axis' with points ls 1, \
"data.txt" using 1:3 title 'Y Axis' with points ls 2
Try it here using this data (in the section titled "Data" - also note that column 3 "Symbol" is noted used, it's mainly there for illustrative purposes):
# This file is called force.dat
# Force-Deflection data for a beam and a bar
# Deflection Col-Force Symbol
0.000 0 5
0.001 104 5
0.002 202 7
0.003 298 7
And in the Plot Script Heading:
set key inside bottom right
set xlabel 'Deflection (m)'
set ylabel 'Force (kN)'
set title 'Some Data'
set style line 1 lc rgb 'red' pt 7
set style line 2 lc rgb 'blue' pt 5
plot "data.txt" using 1:2 title 'Col-Force' with points ls 1, \
"data.txt" using 1:3 title 'Beam-Force' with points ls 2
The one caveat is of course that you have have to reconfigure your data input source.
REFERENCES:
http://www.gnuplotting.org/plotting-single-points/
http://www.gnuplotting.org/plotting-data/
Here is a possible solution (which is a simple extrapolation from gnuplot conditional plotting with if), that works as long as you don't have tens of different symbols to handle.
Suppose I want to plot 2D points in a coordinate system. I have only two symbols, that I arbitrarily represented with a 0 and a 1 in the last column of my data file :
0 -0.29450470209121704 1.2279523611068726 1
1 -0.4006965458393097 1.0025811195373535 0
2 -0.7109975814819336 0.9022682905197144 1
3 -0.8540692329406738 1.0190201997756958 1
4 -0.5559651851654053 0.7677079439163208 0
5 -1.1831613779067993 1.5692367553710938 0
6 -0.24254602193832397 0.8055955171585083 0
7 -0.3412654995918274 0.6301406025886536 0
8 -0.25005266070365906 0.7788659334182739 1
9 -0.16853423416614532 0.09659398347139359 1
10 0.169997438788414 0.3473801910877228 0
11 -0.5252010226249695 -0.1398928463459015 0
12 -0.17566296458244324 0.09505800902843475 1
To achieve what I want, I just plot my file using conditionals. Using an undefined value like 1/0 results in no plotting of the given point:
# Set styles
REG_PTS = 'pointtype 7 pointsize 1.5 linecolor rgb "purple"'
NET_PTS = 'pointtype 4 pointsize 1.5 linecolor rgb "blue"'
set grid
# Plot each category with its own style
plot "data_file" u 2:($4 == 0 ? $3 : 1/0) title "regular" #REG_PTS, \
"data_file" u 2:($4 == 1 ? $3 : 1/0) title "network" #NET_PTS
Here is the result :
Hope this helps
Variable pointype (pt variable) was introduced (I guess) not until gnuplot 5.2.0 (Sept 2017) (check help points).
Just in retrospective, another (awkward) solution would be the following for those who are still using such early versions.
Data:
1 1.0 4 # empty square
2 2.0 5 # filled square
3 3.0 6 # empty circle
4 4.0 7 # filled circle
5 5.0 8 # empty triangle up
6 6.0 9 # filled triangle down
7 7.0 15 # filled pentagon (cross in gnuplot 4.6 to 5.0)
Script: (works from gnuplot>=4.6.0, March 2012; but not necessary since 5.2.0)
### variable pointtype for gnuplot>=4.6
reset
FILE = 'SO23707979.dat'
set key noautotitle
set offsets 1,1,1,1
set pointsize 4
stats FILE u 0 nooutput
N = STATS_records # get the number of rows
p0=x1=y1=NaN
plot for [n=0:N-1 ] FILE u (x0=x1, x1=$1, x0):(y0=y1, y1=$2, y0):(p0=$3) \
every ::n::n w p pt p0 lc rgb "red", \
FILE u 1:2 every ::N-1::N-1 w p pt p0 lc rgb "red"
### end of script
Result:

Resources