I have a problem when plotting a piecewise linear function h(x) = max(0, 1-|x|) (hat function) with gnuplot. My goal is to showcase the interpolation of a polynomial employing these hat functions as basis functions. Thus I need to shift and scale them to different grid points.
My code looks like this:
set key inside bottom right
set xrange [0:1]
set yrange [0:6]
set grid xtics
set style line 1 linecolor rgb '#0060ad' linetype 1 linewidth 2
set ytics 1
set xtics 2**(-3)
set key right top
s(x) = (3.0 * x - 1)
a0 = 2
a1 = -6
a2 = 5
a3 = 5
a4 = -5
a5 = 1
f(x) = a0 + a1*s(x) + a2*(s(x)**2) + a3*(s(x)**3) + a4*(s(x)**4) + a5*(s(x)**5)
max(x, y) = (x > y) ? x:y
h(x) = max(0, 1 - abs(x))
nodal(x, i)=h(2**(3)*x - i) * f(i * 2**(-3))
plot f(x) title "f(x)", nodal(x, 1)
The output however looks like this:
Obviously towards the point where the nodal basis function is not differentiable it fails to nicely plot the function, which looks bad. As I want to include this a thesis I have to submit, it is not something that I could include. Is there any solution for this problem?
Related
So here is what I'm trying to do.
The values on x axis are from 10000, 20000, 30000, ... 100000. I'm trying to write it like this: 10, 20, 30, 40, ... 100 (only x axis)
Is there some way to do this in Gnuplot?
I have this so far:
(data.dat - example of data)
# x y
10000 +1.24241522E-04
11000 +1.28623514E-04
12000 +1.35229020E-04
13000 +1.43767741E-04
14000 +1.53409148E-04
15000 +1.63788695E-04
16000 +1.75429485E-04
17000 +1.88827813E-04
18000 +2.02984785E-04
19000 +2.20830420E-04
...
(my gnuplot script)
set term png
set out 'example.png'
U0 = 0.00732 #parameters for this particular problem
v1 = 68000
b1 = 6550
v2 = 59600
b2 = 6050
I = sqrt(-1)
A(w, w0, b) = ((w0)**2)/(((w0)**2) - ((w)**2) + 2*I*w*b)
f(x) = U0*abs(A(2*pi*x, 2*pi*v1, b1) - A(2*pi*x, 2*pi*v2, b2))
set xlabel "x"
set ylabel "y"
fit f(x) 'data.dat' u 1:2 via U0, v1, b1, v2, b2
plot 'data.dat' u 1:2 t "Title1" w p, U(x) t "Title2"
set out
But how do I do this?
I've tried this example
How to scale the axes in Gnuplot
but it doesn't work.
See below.
# I modified the things a little bit
f(x) = (.... ... ....)/1000
fit f(x) 'data.dat' u ($1/1000.):2 via U0, v1, b1, v2, b2
plot 'data.dat' u ($1/1000.):2 t "Title1" w p, f(x) t "Title2"
But now the fitted function disappears!
How can I modify x-axis without other function disappearing?
Does there exist a line command in gnuplot for this? I'm sure there has to be a more elegant way of writing this insted of dividing each function by a desired factor.
Two possible ways come to my mind:
if you want to avoid too many zeros in the xtic labels, simply set the xtic label format to engineering
set format x "%.0s%c"
This will show, e.g. 10000 and 100000 as 10k and 100k, respectively.
if you scale (in your case: divide) the x values of the data by factor of 1000, gnuplot will take this x range for plotting the function f(x). Since this is will give x values which are a factor of 1000 too small you have to scale your x values by a factor of 1000 accordingly (in your case: multiply).
Code:
### avoid too many zeros in xtic labels
reset session
# create some random test data
set print $Data
A = rand(0)*10+5
B = rand(0)*50000+25000
C = rand(0)*5000+5000
do for [i=10000:100000:500] {
print sprintf("%g %g",i,A*exp(-((real(i)-B)/C)**2))
}
set print
a=1; b=50000; c=5000 # give some reasonable starting values
f(x) = a*exp(-((x-b)/c)**2)
set fit quiet nolog
fit f(x) $Data u 1:2 via a,b,c
set multiplot layout 1,2
set format x "%.0s%c" # set xtics to engineering
plot $Data u 1:2 w p, \
f(x) w l lc "red"
set format x "%g" # set xtics to default
plot $Data u ($1/1000):2 w p, \
f(x*1000) w l lc "red"
unset multiplot
### end of code
Result:
I would like to get a plot like this
which is generated in Gnuplot but plotting from a file.
The Gnuplot scrip that contains all the functions is the following:
set encoding iso_8859_1
set key right top font "Helvetica,17"
set ylabel "Received power, P_t (dBm)" font "Helvetica,18"
set xlabel "Separation distance, r (m)" font "Helvetica,18"
set xtics font "Helvetica,16"
set ytics font "Helvetica,16"
set size 1, 1.2
set terminal postscript color eps enhanced
set grid xtics ytics
set key spacing 1.5
set key box linestyle 1 width 3
set logscale x
set grid xtics mxtics
set output "link-up-test.eps"
h1=1.85
h2=0.5
r(x) = sqrt((h1 - h2)**2 + x**2 )
lmb = 300/865.7
H(x) = sqrt( 1- (4*h1*h2)/(x**2 + (h1 + h2)**2 ) )
theta(x) = 2*pi/lmb*( sqrt((h1 + h2)**2+x**2 ) - sqrt((h1 - h2)**2+ x**2) )
q_e(x) = H(x)**2*(sin(theta(x)))**2 + (1 - H(x)*cos(theta(x)))**2
P_x_G = 4
sigma = 1.94
invsqrt2pi = 0.398942280401433
normal(x,mu,sigma)=sigma<=0?1/0:invsqrt2pi/sigma*exp(-0.5*((x-mu)/sigma)**2)
rnd(x) = 10**(-normal(x,0,sigma)/10)
pot_t(x) = 10*log10( 1000*(P_x_G*1.622*((300/lmb)**2) *0.5*1) / (((4*pi*r(x))**2) *1.2*1)*q_e(x)*rnd(x) )
plot [1:12][] pot_t(x) t "up" w lines ls 1
With this script, I get the following plot
which is has similar form but it does not have the randomness os the function rnd(x) and it does not have the same levels in the y-axis.
I am missing something but I have checked several times the functions several times. I would like to know why is not the same figure.
Regards
I would like to give my solution to this question.
I have used the Box-Muller method to generate Gaussian samples.
h1=1.85
h2=0.5
r(x) = sqrt((h1 - h2)**2 + x**2 )
lmb = 300/865.7
H(x) = sqrt( 1- (4*h1*h2)/(x**2 + (h1 + h2)**2 ) )
theta(x) = 2*pi/lmb*( sqrt((h1 + h2)**2+x**2 ) - sqrt((h1 - h2)**2 + x**2) )
q_e(x) = H(x)**2*(sin(theta(x)))**2 + (1 - H(x)*cos(theta(x)))**2
P_G = 4
sigma = 1.94
normal(x,mu,sigma) = sqrt(-2.0 * log(rand(0))) * cos(2*pi * rand(0)) * sigma + mu
rnd(x) = 10**(-normal(x,0,sigma)/10)
pot_t(x) = 10*log10( 1000*(P_G*1.622*((lmb)**2) *0.5*1) / (((4*pi*r(x))**2) *1.2*1)*q_e(x)*rnd(x) )
set samples 1000
plot [1:12][] pot_t(x) t "up" w lines ls 1
Which creates this plot:
The samples are generated with the function normal(x, mu, sigma).
There is only an issue with this solution
When I plot with set logscale x the plot of points should be denser when the x-axis are more concentrated (see first plot above), but it seems that Gnuplot first makes the logscale of the x-axis and after that takes equidistant samples in figure dealing the log scale as a linear scale. I would appreciate if anyone could answer this or improve the solution.
Regards
There is nothing random about your rnd(x) function. Just plot rnd(x) and you can see that. Why are you not using gnuplot's rand() function in conjunction with your normal distribution?
I want to reproduce this effect in gnuplot:
How can I achive it? If it can't be done, what software can I use to reproduce it?
Using a 2d kernel for every pixel can be done inside gnuplot. That way, more dense accumulations get brighter than single pixels. Check show palette rgbformulae and the respective chapter in the help to change the colours.
set term wxt size 300,300 background rgb 0
set view map
set samp 140
set dgrid3d 180,180, gauss kdensity2d 0.2,0.2
set palette rgbform 4,4,3
splot "+" us 1:(sin($1/3)**2*20):(1) with pm3d notitle
Disclaimer: It can be done with gnuplot as instructed in this answer but you should probably consider a different tool to draw this particular type of plot.
There is at least one way to do it, with preprocessing of the data. The idea is to mimic the glow effect by using a Gaussian kernel to smear the data points. Consider the following data, contained in a file called data:
1 2
1 2.1
1.1 2.2
2 3
3 4
I have purposely placed the first 3 points close to each other to be able to observe the intensified glow of neighboring points. These data look like this:
Now we smear the data points using a 2D Gaussian kernel. I have written the following python code to help with this. The code has a cutoff of 4 standard deviations (sx and sy) around each point. If you want the glow to be a circle, you should choose the standard deviations so that the sx / sy ratio is the same as the ratio of the x/y axes lengths in gnuplot. Otherwise the points will look like ellipses. This is the code:
import numpy as np
import sys
filename = str(sys.argv[1])
sx = float(sys.argv[2])
sy = float(sys.argv[3])
def f(x,y,x0,y0,sx,sy):
return np.exp(-(x-x0)**2/2./sx**2 -(y-y0)**2/2./sy**2)
datafile = open(filename, 'r')
data = []
for datapoint in datafile:
a, b = datapoint.split()
data.append([float(a),float(b)])
xmin = data[0][0]
xmax = data[0][0]
ymin = data[0][1]
ymax = data[0][1]
for i in range(1, len(data)):
if(data[i][0] < xmin):
xmin = data[i][0]
if(data[i][0] > xmax):
xmax = data[i][0]
if(data[i][1] < ymin):
ymin = data[i][1]
if(data[i][1] > ymax):
ymax = data[i][1]
xmin -= 4.*sx
xmax += 4.*sx
ymin -= 4.*sy
ymax += 4.*sy
dx = (xmax - xmin) / 250.
dy = (ymax - ymin) / 250.
for i in np.arange(xmin,xmax+dx, dx):
for j in np.arange(ymin,ymax+dy, dy):
s = 0.
for k in range(0, len(data)):
d2 = (i - data[k][0])**2 + (j - data[k][1])**2
if( d2 < (4.*sx)**2 + (4.*sy)**2):
s += f(i,j,data[k][0],data[k][1],sx,sy)
print i, j, s
It is used as follows:
python script.py data sx sy
where script.py is the name of the file where the code is located, data is the name of the data file, and sx and sy are the standard deviations.
Now, back to gnuplot, we define a palette that mimics a glowing pattern. For isolated points, the summed Gaussians yield 1 at the position of the point; for overlapping points it yields values higher than 1. You must consider that when defining the palette. The following is just an example:
set cbrange [0:3]
unset colorbox
set palette defined (0 "black", 0.5 "blue", 0.75 "cyan", 1 "white", 3 "white")
plot "< python script.py data 0.05 0.05" w image
You can see that the points are actually ellipses, because the ratio of the axes lengths is not the same as that of the standard deviations along the different directions. This can be easily fixed:
plot "< python script.py data 0.05 0.06" w image
Set a black background, and then plot your dataset several time in different colours with decreasing pointsize.
set term wxt backgr rgb "black"
plot sin(x) w p pt 7 ps 2 lc rgb 0x00003f not, \
sin(x) w p pt 7 ps 1.5 lc rgb 0x00007f not, \
sin(x) w p pt 7 ps 1 lc rgb 0x0000af not, \
sin(x) w p pt 7 ps .5 lc rgb 0x0000ff
Alternatively, some combination of splot with pm3d,set dgrid3d gauss kdensity2d, and set view map, combined with a suitable palette, can be used, see my other answer.
I want to plot a right triangle with hypothenuse parallel to the slope of a curve in loglog scale. However, gnuplot behaves funky:
set terminal postscript eps enhanced "Helvetica" 22
a1 = 64459.7;
a2 = -1.90748;
func(x) = a1*x**a2
X1 = 1e+4;
Y1 = 1e-4;
X2 = 2e+4;
Y2 = Y1 + func(X1) - func(X2)
set logscale xy
set format x "10^{%T}"
set format y "10^{%T}"
set key top right
set output 'temp.eps'
set object 1 poly from X1,Y1 to X2,Y1 to X1,Y2 to X1,Y1 fs empty border 1
set xrange [0.8e+4:1e+5]
plot func(x) title sprintf("a line with slope %1.2f",a2)
unset object 1
and outputs
Perhaps in log-log scale the command set object behaves differently when in log-log scale, otherwise i have no idea...
the right answer is:
Y2 = Y1 * 10**(a2 * log10(X1 / X2) );
p.s. moderators, feel free to delete the question
I'm trying to reproduce a figure I've found on a linear algebra book using gnuplot. This is the original image
You can see an intersection between two planes described by the two equations:
2u + v + w = 5
4u - 6v = -2.
I suppose that in order to plot the first equation using gnuplot I have to transform it in the form:
splot 5 - 2*x - y
where u -> x; v -> y and w -> z which is the free variable. But the result is very different from what expected. Any clue?
The approach you outline makes sense, however, the results may be far from what you expect.
I propose you draw single lines, using the arrow function in gnuplot.
This example will generate a plot very similar to the one you showed (only one plane, though):
set term gif
set output "demo_plane.gif"
# define your axis limits:
xmax = 6.5
xmin = -1.5
ymax = 8.5
ymin = -1.5
zmax = 5.5
zmin = -0.5
set xrange [xmin:xmax]
set yrange [ymin:ymax]
set zrange [zmin:zmax]
# remove the original axis
unset border
unset xtics
unset ytics
unset ztics
# define you data points:
x1 = 3.0
y1 = -1.0
z1 = 0.0
x2 = -1.0
y2 = 7.0
z2 = 0.0
x3 = -3.0
y3 = 7.0
z3 = 4.0
x4 = 1.0
y4 = -1.0
z4 = 4.0
# define 'arrow' without head:
set arrow 1 from x1,y1,z1 \
to x2,y2,z2 nohead
set arrow 2 from x2,y2,z2 \
to x3,y3,z3 nohead
set arrow 3 from x3,y3,z3 \
to x4,y4,z4 nohead
set arrow 4 from x4,y4,z4 \
to x1,y1,z1 nohead
# draw new axis manually (again, using arrow):
set arrow 5 from 0,0,0 \
to 6,0,0
set arrow 6 from 0,0,0 \
to 0,6,0
set arrow 7 from 0,0,0 \
to 0,0,5
# annotate axis labels:
set label "u" at 6.25,0,0
set label "v" at 0,6.25,0
set label "w" at 0,0,5.25
# plot will not show when empty, include dummy plot command:
set parametric
splot x1, y1, z1 not
With a little rotation you will get a figure like this: