Gnuplot: triangle in log-log axes - gnuplot

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

Related

Plotting piecewise linear functions with gnuplot inaccurately

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?

How to plot a function of functions

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?

Display a line outside the axis limits in Octave

I'd like to draw a line that extends beyond the limits of the axis. I've tried setting the clipping property to off like this:
figure
axis([0, 10, 0, 10])
hold on
set(gca,'outerPosition',[0, 0.5, 1, 0.5])
lh = line([2, 8],[8, -5]);
set(lh, 'clipping', 'off')
print('line_plot.png')
I get a figure that looks like this:
Is there a way to make the line extend beyond the x-axis? I'm using gnuplot and AquaTerm. Would this be possible in another terminal?
In gnuplot, I would recommend annotating an arrow, which can extend beyond the axis. Here's a minimal example to achieve what you outline in your question:
# define the location of your plot:
bm = 0.15
lm = 0.12
rm = 0.95
tm = 0.95
set lmargin at screen lm
set rmargin at screen rm
set bmargin at screen bm
set tmargin at screen tm
# define your axis limits:
xmax = 10.0
xmin = 0.0
ymax = 10.0
ymin = 0.0
set xrange [xmin:xmax]
set yrange [ymin:ymax]
# define you data points:
xstart = 2
ystart = 8
xend = 8
yend = -5
# convert points into screen coordinates:
dx_rel = (rm-lm)/(xmax-xmin)
dy_rel = (tm-bm)/(ymax-ymin)
xstart_rel = lm + dx_rel * xstart
ystart_rel = bm + dy_rel * ystart
xend_rel = lm + dx_rel * xend
yend_rel = bm + dy_rel * yend
# define 'arrow' without head in screen coordinates:
set arrow 1 from screen xstart_rel,ystart_rel \
to screen xend_rel,yend_rel nohead
# plot will not show when empty, include dummy plot command:
set parametric
plot xstart, ystart not
The clip option you refer to in gnuplot does not allow you to extend your plot past the axis. It is meant to remove data points close to the axis to avoid symbols overlaying with those axis.
The arrow, however, can be specified in screen coordinates (the screen in this case is the plot window) which allows you to draw outside the axis.
To match specific data-coordinates, you have to translate those into screen-coordinates. This will only work reliably when you define you plot boundaries in those screen coordinates. That way, you can calculate where each data point will be on the screen.
When seting the arrow, make sure to use screen before the coordinates to indicate the right coordinate system.
The script above will give you this plot:

Drawing a plane on a cartesian plane using gnuplot

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:

gnuplot: 3d surface, with 2d line graph on the y,z axis wall

I've made a 3d surface plot in gnuplot, and I'm wondering if it's possible to plot an unrelated 2d line graph on the 'wall' of the y,z axis.
So in essence, I take my x,y line plot but paste it on to the y,z axis.
Similar to a contour plot on the x,y, under a 3d surface, but different.
This may not be precisely what you are looking for, but it is a way to plot a function on a 'wall' of your splot box:
#!/usr/bin/env gnuplot
set term png
set output 'test.png'
# this is the function you want on the wall
myfun(x,y) = y**2
# set the ranges manually
xmin = -10
xmax = 10
ymin = -10
ymax = 10
x_range = xmax - xmin
y_range = ymax - ymin
scaler = 0.001
x1 = xmin - x_range*scaler
x2 = xmin + x_range*scaler
x3 = xmax - x_range*scaler
x4 = xmax + x_range*scaler
y1 = ymin - y_range*scaler
y2 = ymin + y_range*scaler
y3 = ymax - y_range*scaler
y4 = ymax + y_range*scaler
xminwall(x,y) = (x > x1 && x < x2) ? myfun(x,y) : 1/0
xmaxwall(x,y) = (x > x3 && x < x4) ? myfun(x,y) : 1/0
yminwall(x,y) = (y > x1 && y < x2) ? myfun(x,y) : 1/0
ymaxwall(x,y) = (y > x3 && y < x4) ? myfun(x,y) : 1/0
splot sin(x), xminwall(x,y)
Here is the result:
What the script does is plots the function you want to plot on the wall (myfun(x,y)) and does a splot of it, restricted to values that are very close to the wall. The surface mesh has a certain number of gridpoints, and one of those points is always at the x and y limits.
In this example, if I had just done splot sin(x), y**2, I would have gotten two overlapping surfaces.
I made four functions (xminwall, etc.) so you can plot on the wall at the x/y range minimum/maximum walls. Note that mufun(x,y) has to be a function of the correct x and y in order for the plot to show up properly on the wall, otherwise you might get a straight line.

Resources