Is there any way to specify a yrange using the graph position specifier?
I want to plot a function inside a specific region of the canvas. I have absolute values for the xrange, but for the yrange I want it to go from, for example, y>graph 0.7 and y<graph 0.8, i.e, I want the y values of the function vary from 70% till 80% of the values of the actual yrange. More specifically, I want something like this:
plot (x<x_min || x>x_max) || (y<graph 0.7 || y>graph 0.8) ? 1/0 : the_function(x)
Well, I tried to do this, but it didn't work: gnuplot returns an error. I also searched for a solution, but had no success.
Do you have any idea of how to do this?
You cannot directly use graph for coordinates used inside plot. This works only for labels, objects and arrows. Gnuplot evaluates the function on the whole x-range and then determines the automatic y-range. So you cannot have access to an automatically computed y-range at the time the function is evaluated.
Here is how you can achieve that with other means.
First you plot the complete function using the unknown terminal. This determines the y-range which would have been used for the complete function. The values are stored in the variables GPVAL_Y_MIN and GPVAL_Y_MAX. Now you can replot the function using these values as constraints:
set terminal unknown
f(x) = sin(x)
set xrange [0:10]
plot f(x)
set terminal pngcairo size 600,300 lw 2
unset key
set output 'test.png'
set samples 1000
graph_y = GPVAL_Y_MAX - GPVAL_Y_MIN
y0 = GPVAL_Y_MIN
set yrange[y0 : y0 + graph_y]
plot (y = f(x), (y < y0 + 0.7*graph_y || y > y0 + 0.8*graph_y) ? 1/0 : y)
1/0 only works with data points. You can use the special data file "+" for this purpose, which in the end is the same as plotting a function, where gnuplot is sampling the function at discrete intervals:
set xrange [-2*pi:2*pi]
plot "+" u ($1):($1 > -pi && $1 < pi ? sin($1) : 1/0) w l
Related
I want to plot a series of points, a plane and the intersection points with that plane using gnuplot. In order to do this, I created the following gnuplot script:
set title 'Homogeneous field with plane intersection'
set xlabel 'x'
set ylabel 'y'
set zlabel 'z'
set parametric
splot 'points.txt' with linespoints, 'intersectionPoints.txt' with points
pointtype 7 lc rgb 'red',
60 + 0 * u, u, v
The script produces the following plot:
Everything works fine, however the size of the parametric plane is way too small. How can I get gnuplot to automatically adjust the size of the plane to roughly match the dimensions of the rest of the plot?
You have to set the ranges for the two parameters u and v, for example
set urange [-50:250]
set vrange [-20:20]
From help parametric: " Currently the default range for these parametric variables is [-5:5]. Setting the ranges to something more meaningful is expected.".
I want to plot two functions in different ranges in Gnuplot. As an example, I want to plot f(x) for xrange [0:0.5] and g(x) for xrange [0.5:1], both in a same graph.
What should I do for this?
You have at least two different solutions :
1) create a "heavyside" function :
f(x) = ... define your first function
g(x) = ... define your second function
h(x) = (x<0.5)?f(x):g(x)
plot h(x)
2) if you need some control on the color of each function, you could do
plot (x<0.5?f(x):1/0) lc 1, (x>0.5?g(x):1/0) lc 2
I am new to gnuplot. I am trying to plot 3d vector fields. I know that I have to create a data file that has six columns representing x, y, z, deltax,deltay, deltaz.
I wondering if it is possible to define a function f(x,y,z) and have gnuplot create the data file I desire in order to plot the vectors.
If so, how do I go about doing this?
You can use the special file name ++ to create a 2d grid on which you can define you vector field:
set xrange [-10:10]
set yrange [-10:10]
set samples 100
set isosamples 100
vx(x,y,z) = ...
vy(x,y,z) = ...
vz(x,y,z) = ...
z(x,y) = ...
splot '++' using 1:2:(z($1,$2)):(vx($1,$2,z($1,$2))):(vy($1,$2,z($1,$2))):(vz($1,$2,z($1,$2))) with vectors
This plots a vector field (vx,vy,vz) on the surface z(x,y). Gnuplot cannot generate a 3d grid.
You could try to simulate such a real 3d vector field with a loop:
z(i) = -10 + i*(20.0/99.0)
splot for [i=1:100] '++' using 1:2:(z(i)):(vx($1,$2,z(i))):(vy($1,$2,z(i))):(vz($1,$2,z(i))) with vectors lt 1
As example considert the following script for a central force:
lim = 2
N = 6
set xrange [-lim:lim]
set yrange [-lim:lim]
set zrange [-lim:lim]
set samples N
set isosamples N
sc= 0.3
r(x,y,z) = sqrt(x**2 + y**2 + z**2)
gx(x,y,z) = sc/(x**2 + y**2 + z**2) * x/r(x,y,z)
gy(x,y,z) = sc/(x**2 + y**2 + z**2) * y/r(x,y,z)
gz(x,y,z) = sc/(x**2 + y**2 + z**2) * z/r(x,y,z)
z(i) = -lim + 2*i*lim/(N - 1.0)
unset key
set xyplane 0
splot for [i=1:N] '++' using 1:2:(z(i)):(gx($1,$2,z(i))):(gy($1,$2,z(i))):(gz($1,$2,z(i))) with vectors lt 1
with the output
Here an answer that would apply to a 3d surface plot. I'm sure this can be expanded to work for a vector field as well - a matter of writing the function which is outside my comfort zone.
You would plot your function to a table rather than a graphic output and then plot the graph using the table you just have produced (and could inspect, edit etc. before). Sample:
# output to a file with the data
set table "so.dat"
# plot your function
splot [-2:2][-2:2] exp(-(x**2 + y**2))*cos(x/4)*sin(y)*cos(2*(x**2+y**2))
# switch the graphic screen on again and plot from your file
unset table
unset ztics # avoiding cluttered ztics
splot "so.dat" u 1:2:3 w l
yields
Sample taken from Philipp K. Janert, Gnuplot In Action
I want to create a streamline like arrow lines in Gnuplot,I already have the data points that I needed, so I think my problem is not the same as this post says and different from this post because I have already obtain the data needed for stramlines.
What I have done is like this:
So the red lines are vectors show flow field and green line is streamlines to guide the readers the direction of the flux. And all the large blue arrows are my aim to be plotted in GNUPLOT. I have kown how to plot middle arrows as this post has shown but what code I need to do if I want to plot more arrows along the lines?
To be more detailed, How can I plot like this:
I supply my data file here :
velocity.txt is for vector flow field data as "index,X,Y,vx,vy,particle-numbers"
line.txt is for streamline data as "X,Y"
and My gnu file is bleow:
set terminal postscript eps size 108,16 enhanced font "Arial-Bold,100"
set output 'vector.eps'
unset key
set tics
set colorbox
set border 0
set xtics 2
#set xlabel 'x'
#set ylabel 'y'
set xrange [0:108]
set yrange [0:16]
#set cbrange [0:40]
set nolabel
set style line 4 lt 2 lc rgb "green" lw 2
plot 'velcoity.txt' u 2:3:(250*$4):(250*$5) with vectors lc 1,'line.txt' u 1:2 ls 4
Thank you!
To plot arrows along a line you can again use the vectors plotting style like you do already for the stream field.
But to get a proper plot you must consider several points:
Usually gnuplot limits the size of the arrow heads to a fraction of the arrow length. So, if you want to plot a continuous line with arrows heads, the arrows themselves should have a very short length. To avoid downscaling of the arrow heads, use the size ... fixed option, which is available only since version 5.0
You have only the trajectory, x and y values, of the line. To extract the arrow direction, the simplest approach would be to use the difference between two neighbouring points (or at a distance of two or three points).
You can extract these differences in the using statement. As pseudo code, one could do the following:
if rownumber modulo 10 == 0:
save x and y values
else if rownumber modulo 10 == 1:
draw arrow from previous point to current point, only with a head
else
ignore the point.
Putting this pseudo-code in the using statement gives the following:
ev = 10
avg = 1
sc = 0.1
plot 'line.txt' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
To make things more flexible, I introduced some variables: ev tells you the difference count between two arrows heads, avg the distance between two points used to calculate the arrow direction, and sc the length of the arrow shaft.
As further improvement you can use the length of the stream field arrows to colour the stream field vectors. This gives the following script
reset
unset key
set tics
set colorbox
set border 0
set xtics 2
set autoscale xfix
set autoscale yfix
set autoscale cbfix
set style line 4 lt 2 lc rgb "green" lw 2
ev=30
avg=3
sc=0.1
field_scale=500
plot 'velcoity.txt' u 2:3:(field_scale*$4):(field_scale*$5):(sqrt($4**2+$5**2)) with vectors size 1,15,45 noborder lc palette,\
'line.txt' u 1:2 ls 4 w l,\
'' u (prev_x = (int($0)%ev == 0 ? $1 : prev_x), prev_y = (int($0)%ev == 0 ? $2 : prev_y), int($0)%ev == avg ? $1 : 1/0):2:(sc*(prev_x-$1)):(sc*(prev_y-$2)) w vectors backhead size 2,20,90 fixed ls 4
With the result (qt terminal):
I want to create and plot a set of random points within the boundaries of an ellipsoid using gnuplot. Is it possible to do this directly in gnuplot, or would I need to generate my random data points in an external program?
Ultimately I would like to produce an ellipsoid figure similar to this ellipse figure.
There are some examples on the use of rand and cylindrical/spherical coordinates, but I'm not sure how to generate the random points inside the boundaries of an ellipsoid.
Based on #Bernhard's answer, here is how you can do that with gnuplot only. To reuse a random number, you can put the two rand calls and the assignments to variables in the first argument of the using statement, separated by commas. The using statements are evaluated from left to right, so you can access those variables in all following using parameters.
To demonstrate this, see the following examples:
set samples 1000
plot '+' using (x=rand(0), y=rand(0), x):(y)
Applying this to the ellipsoid, this gives the script:
a=3
b=2
phi=30*pi/180
max(x,y) = (x > y ? x : y)
set xrange[-max(a,b):max(a,b)]
set yrange[-max(a,b):max(a,b)]
set offset 0.1,0.1,0.1,0.1
set samples 2000
ex(x, y) = a*(2*x-1)
ey(x, y) = b*(sqrt(1-((2*x-1))**2))*(2*y-1)
unset key
plot '+' using (x=rand(0), y=rand(0), ex(x,y)*cos(phi)-ey(x,y)*sin(phi)):\
(ey(x,y)*cos(phi)+ex(x,y)*sin(phi)) pt 7 ps 0.5
with the result:
This, however, leads to an apparently unequal distribution of the points (see the agglomarations at the ellipse's ends, see #andyras's comment). To avoid this, here is how you can filter equally distributed random points to be inside the ellipsoid:
a=3
b=2
set angles degree
phi=30
max(x,y) = (x > y ? x : y)
set xrange[-max(a,b):max(a,b)]
set yrange[-max(a,b):max(a,b)]
set offset 0.1,0.1,0.1,0.1
set samples 2000
set size ratio 1
check(x, y) = (((x/a)**2 + (y/b)**2) <= 1)
unset key
plot '+' using (x=2*a*(rand(0)-0.5), y=2*b*(rand(0)-0.5), \
check(x,y) ? x*cos(phi)-y*sin(phi) : 1/0):\
(x*sin(phi)+y*cos(phi)) pt 7 ps 0.5
This gives the much better result:
Extending this to three dimensions:
a=3
b=1
c=1
set angles degree
phi=30
mx(x,y) = (x > y ? x : y)
max(x,y,z) = mx(mx(x,y), mx(x,z))
set xrange[-max(a,b,c):max(a,b,c)]
set yrange[-max(a,b,c):max(a,b,c)]
set zrange[-max(a,b,c):max(a,b,c)]
set offset 0.1,0.1,0.1,0.1
set samples 2000
set size ratio 1
set ticslevel 0
set view 60, 330
check(x, y, z) = (((x/a)**2 + (y/b)**2 + (z/c)**2) <= 1)
unset key
splot '+' using (x = 2*a*(rand(0)-0.5), \
y = 2*b*(rand(0)-0.5), \
z=2*c*(rand(0)-0.5), \
check(x,y,z) ? x*cos(phi)-y*sin(phi) : 1/0):\
(x*sin(phi)+y*cos(phi)):(z) pt 7 ps 0.5
with the result:
I didn't find a method to reuse the rand(0) in the parametric plot example that you showed, but with an internal call to command line tools, you can do that with some modifications:
unset key
a=3
b=2
set xrange [-a:a]
set yrange [-b:b]
set style function dots
plot "<seq 1000 | awk '{print rand(), rand()}'" using (a*(2*$1-1)):(b*(sqrt(1-((2*$1-1))**2))*(2*$2-1))
To convert this to 3D is left as an exercise to the reader (just continue on these expressions)