I'm solving the pendulum's equation of motion, and I need to create an animation in GNUplot that shows the evolution of the system.
R4K provides me with the solution point by point, and this solution is stored in a .dat file named 'd' in columns 2 and 3. These are the orders given to GNUplot:
set xrange [-2:2]
set yrange [-2:2]
set pointsize 2
set style line 2 lc rgb '#0060ad' pt 7
set object circle at first 0,0 size scr 0.01 \
fillcolor rgb 'black’ fillstyle solid
do for [ii=1:3762] {
plot 'd.dat' using 2:3 every ::ii::ii linestyle 2
pause 0.002
}
I now want to connect the circle in [0,0] to the moving point plotted from d.dat with a moving line; how can I do it? I found a solution (kind of) here, but still I don't know how to tell GNUplot to search for a certain point in 'd.dat', different every time, and to draw the line between it and the centre.
The solution of user8153 is so far the best. Let me give a trial. If I were you I would have use arrows that update their positions with the moving end dynamically, since the every command loads one point at time. GNUPLOT provides environment variables such as GPVAL_X_MIN, GPVAL_X_MAX, GPVAL_Y_MIN,... that can be useful:
set xrange [-2:2]
set yrange [-2:2]
set pointsize 2
set style line 2 lc rgb '#0060ad' pt 7
set object circle at first 0,0 size scr 0.01 \
fillcolor rgb 'black’ fillstyle solid
do for [ii=1:3762] {
plot 'd.dat' using 2:3 every ::ii::ii linestyle 2
# makes GPVAL_ variables available
xpos = GPVAL_X_MIN; ypos = GPVAL_Y_MIN # or MAX does not matter since you are
# loading one point at time.
unset arrow # Remove the one of the previous graph
set arrow from 0, 0 to xpos, ypos nohead lc rgb 'black'
replot
pause 0.002
}
I have no data to debug this code snippet, but I would have done something along this line. Later versions of GNUPLOT allow to use stats command that avoids replot (replot could have an effect here on the persistence of images of the film but I am not sure). You can also try something along the line
set xrange [-2:2]
set yrange [-2:2]
set pointsize 2
set style line 2 lc rgb '#0060ad' pt 7
set object circle at first 0,0 size scr 0.01 \
fillcolor rgb 'black’ fillstyle solid
do for [ii=1:3762] {
stats 'd.dat' using 2:3 every ::ii::ii # applied the statistical summary of
# the data file
xp = STATS_min_x; yp = STATS_min_y
unset arrow
set arrow from 0, 0 to xp, yp nohead lc rgb 'black'
plot 'd.dat' using 2:3 every ::ii::ii linestyle 2
pause 0.002
}
I have never used STATS with the every command (let me know the output just for fun).
Hope that helps
Related
I need to plot a two variable function on Gnuplot when it intersects with 0, that is: f(x,y)=0. It will mean a 2D plot rather than 3D.
My attempt up to now is:
set term cairolatex eps standalone size 6in,6in lw 7
set key box opaque samplen 6
set key spacing 1.5
set key Right
set key height 2
set key width 3
f(x,y)=...
set output 'V.tex'
plot f(x,y)=0 title '\small${\hat{V}=2}$' lc rgb "black"
set out
but it returns function to plot expected.
Just in case, the workaround given in 5.2 section of the Gnuplot FAQ in http://www.gnuplot.info/faq/faq.html does not produce a .tex file that I can compile.
I tried to combine the code from the FAQ (#gdupras's answer) with the code you showed at first.
set term cairolatex eps standalone size 6in,6in lw 7
set key box opaque samplen 6
set key spacing 1.5
set key Right
set key height 2
set key width 3
f(x,y) = y - x**2 / tan(y)
set contour base
set cntrparam levels discrete 0.0
unset surface
set table $TEMP
splot f(x,y)
unset table
set output 'V.tex'
plot $TEMP w l title '\small${\hat{V}=2}$' lc rgb "black"
set out
In my environment, this code generates "V.tex" and I get the following figure (PDF converted to PNG) after compiling.
This is documented in the gnuplot FAQ: http://www.gnuplot.info/faq/faq.html
From that page:
5.2 Implicit defined graphs
Implicit graphs or curves cannot be plotted directly in gnuplot . However there is a workaround.
gnuplot> # An example. Place your definition in the following line:
gnuplot> f(x,y) = y - x**2 / tan(y)
gnuplot> set contour base
gnuplot> set cntrparam levels discrete 0.0
gnuplot> unset surface
gnuplot> set table $TEMP
gnuplot> splot f(x,y)
gnuplot> unset table
gnuplot> plot $TEMP w l
The trick is to draw the single contour line z=0 of the surface z=f(x,y), and store the resulting contour curve to a temporary file or datablock.
I am trying to plot a simple linear surface of the equation x + y + 2z = 0. This is my file:
set xrange [-4:4]
set yrange [-4:4]
set zrange [-4:4]
set xlabel 'x'
set ylabel 'y'
set zlabel 'z'
set xyplane at -4.0
unset xzeroaxis
unset yzeroaxis
unset zzeroaxis
set border 1023-128
set xtics out nomirror
set ytics out nomirror
set ztics out
set xtics add ('' -4)
set label 1 "{/:Italic x} + {/:Italic y} + 2{/:Italic z} = 0" at 4,4.2,-2 font 'Times New Roman, 11'
set arrow 1 from 0,0,-4 to 0,0,4 filled
set arrow 2 from 0,-4,0 to 0,4,0 filled
set arrow 3 from -4,0,0 to 4,0,0 filled
set arrow 4 from 3.9,4.1,-2.1 to 3.6,3.6,-2.5
unset key
set pm3d lighting primary 0.5 specular 0.6
set style fill transparent solid 1 noborder
set palette defined (0 "cyan", 1 "green")
unset colorbox
set pm3d depthorder
splot -x/2-y/2 with pm3d
The result
I'm using arrows to show the axis, since they seem to be stuck to the xy plane, and moving it causes further issues with the tics and border. But now the problem is that they are completely occluded by the surface. Is there a setting which allows to appear in front when they "pierce" the surface? I'd like to make the surface semitransparent, but the problem is clearer with these settings.
I guess your original idea, i.e. "piercing" a 3D surface with an arrow or line does not work right away in gnuplot, because gnuplot will not calculate the piercing points automatically. Please correct me if I am wrong and let me know in case there might be a simple solution to this.
As you did in your simple case, you can just split the arrow at the origin, because you already know the piercing point. However, what do you do if the surface is irregular or has several piercing points?
Solution: take the effort to create a segmented 3D arrow and let gnuplot automatically show and hide the surfaces as needed. This is probably getting close to what you had in mind. However, this solution will show surprises when you want to change the color of the arrows. So, there is still room for improvement.
Code: (simple version with arrows just along x,y,z axes)
### arrows "piercing" a 3D surface
reset session
set view equal xyz
set xyplane relative 0.0
set xrange [-4:4]
set yrange [-4:4]
set zrange [-4:4]
# create 3D arrow
r = 0.01 # radius of arrow
rHead = 0.1 # radius of arrrowhead
n = 6 # corners of arrow
set print $myArrow
do for [h=-100:90] {
do for [a=360/n:360:360/n] {
print sprintf("%g %g %g",r*cos(a),r*sin(a), h/100.)
}
print ""
}
do for [h=90:100] {
do for [a=360/n:360:360/n] {
print sprintf("%g %g %g",rHead*(100-h)/10.*cos(a), \
rHead*(100-h)/10.*sin(a), h/100.)
}
print ""
}
set print
unset key
unset colorbox
set pm3d depthorder
set samples 100
set isosamples 100
set view 65,46,1.3
# function to demonstrate "piercing"
f(x,y) = (sin(x*3)/x + sin(y*3)/y - 3)/2
splot \
f(x,y) w pm3d, \
$myArrow u 1:2:($3*4):(0) w pm3d lc rgb var, \
$myArrow u 2:($3*4):1:(0) w pm3d lc rgb var, \
$myArrow u ($3*4):1:2:(0) w pm3d lc rgb var
### end of code
Result:
gnuplot> help layer
A gnuplot plot is built up by drawing its various components in a fixed order.
This order can be modified by assigning some components to a specific layer
using the keywords `behind`, `back`, or `front`. For example, to replace the
background color of the plot area you could define a colored rectangle with the
attribute `behind`.
set object 1 rectangle from graph 0,0 to graph 1,1 fc rgb "gray" behind
The order of drawing is
behind
back
the plot itself
the plot legend (`key`)
front
Within each layer elements are drawn in the order
grid, axis, and border elements
pixmaps in numerical order
So basically you need to add the "front" attribute to the objects you want to appear in front of the plot.
This question already has answers here:
Plotting multiple pm3d surfaces each having its own palettes in gnuplot
(2 answers)
Closed 2 years ago.
I have two 3d surfaces. Is it possible to use a different color palette for each surface with splot?
The script that i used and the graph that is produced follow:
set title "Thermal efficiency versus turbine inlet temperature and degree of superheating diagram"
set termopt enhanced
set grid
set key top left
set xlabel "ΔT_{super} [^{o}C]"
set ylabel "T_{3} [^{o}C]"
set zlabel "n_{th} [-]"
#set datafile missing '0.000000000000000000e+00'
#set datafile missing '0.000000'
set hidden3d
set pm3d
set view 60,60
set palette rgb 7,5,15 #black-blue-red-yellow
splot "para_sub_dtsuper_iso_dtppreg_1.txt" using ($1):($2-273.15):($5) title "Conventional ORC" with lines lt 1 lw 1.5,\
"para_sub_dtsuper_iso_dtppreg_1.txt" using ($1):($2-273.15):($6) title "Regenerative ORC" with lines lt 1 lw 1.5,\
pic_1
On a side not, i would like to know if it is possible to produced mesh color-gradient surfaces like in the picture below:
pic_2
Thank you in advance.
Here is a revised version of the plot that theozh linked to. It shows two surfaces in the same plot, one using color mapping via the built-in palette mechanism and the other effectively doing the same sort of color mapping explicitly. The development version of gnuplot has automated this so that you can construct and use multiple palettes by assigning a name to each one.
#
# Demonstrate construction and use of a separate palette
#
# This method works in 5.2 but requires "lc rgb variable"
# rather than the more natural "fillcolor rgb variable".
# "set pm3d interpolate" breaks the color mapping of this method
#
# This creates a palette equivalent to
# set palette defined (0 "dark-blue", 1 "white")
#
array blues[256]
do for [i=1:256] {
blues[i] = int( (0x7f + (i-1)/(255.) * 0xffff80) );
}
#
# This is the equivalent of
# set cbrange [0:5]
blues_min = 0
blues_max = 5
#
# This function maps z onto a palette color
#
blues(z) = (z <= blues_min) ? blues[1] \
: (z >= blues_max) ? blues[256] \
: blues[ floor(255. * (z-blues_min)/(blues_max-blues_min)) + 1]
F1(x,y) = sqrt(x*y)
F2(x,y) = (x*y)**(1./3)
set samples 41; set isosamples 41
set cbrange [0:5]; set xrange [0:5]; set yrange [0:5]
set palette cubehelix negative
unset colorbox
# Needed for proper occlusion of hidden surface
set pm3d depthorder
# Place a thin border around each facet of the surfaces
set pm3d border lc "black" lw 0.5
set title "Top surface uses hand-constructed 'blues' palette via rgb variable\n".\
"Bottom surface uses 'set palette cubehelix negative'"
set title offset 0,1
splot '++' using 1:2:(F1($1,$2)):(blues(F1($1,$2))) with pm3d lc rgb variable \
title "F1(x,y) using 1:2:3:4 with pm3d lc rgb variable", \
'++' using 1:2:(F2($1,$2)) with pm3d \
title "F2(x,y) using 1:2:3 with pm3d"
I apologize for the delayed response. This is what i was looking for. I am grateful to both of you!
Is it possible in Gnuplot to emulate the drawing style of an analogue oscilloscope, meaning thinner+dimmisher lines on larger amplitudes, like this:?
The effect you see in the oscilloscope trace is not due to amplitude, it is due to the rate of change as the trace is drawn. If you know that rate of change and can feed it to gnuplot as a third column of values, then you could use it to modulate the line color as it is drawn:
plot 'data' using 1:2:3 with lines linecolor palette z
I don't know what color palette would work best for your purpose, but here is an approximation using a function with an obvious, known, derivative.
set palette gray
set samples 1000
plot '+' using ($1):(sin($1)):(abs(cos($1))) with lines linecolor palette
For thickness variations, you could shift the curve slightly up and down, and fill the area between them.
f(x) = sin(2*x) * sin(30*x)
dy = 0.02
plot '+' u 1:(f(x)+dy):(f(x)-dy) w filledcurves ls 1 notitle
This does not allow variable colour, but the visual effect is similar.
Another approach:
As #Ethan already stated, the intensity is somehow proportional to the speed of movement, i.e. the derivative. If you have sin(x) as waveform, the derivative is cos(x). But what if you have given data? Then you have to calculate the derivative numerically.
Furthermore, depending on the background the line should fade from white (minimal derivative) to fully transparent (maximum derivative), i.e. you should change the transparency with the derivative.
Code:
### oscilloscope "imitation"
reset session
set term wxt size 500,400 butt # option butt, otherwise you will get overlap points
set size ratio 4./5
set samples 1000
set xrange[-5:5]
# create some test data
f(x) = 1.5*sin(15*x)*(cos(1.4*x)+1.5)
set table $Data
plot '+' u 1:(f($1)) w table
unset table
set xtics axis 1 format ""
set mxtics 5
set grid xtics ls -1
set yrange[-4:4]
set ytics axis 1 format ""
set mytics 5
set grid ytics ls -1
ColorScreen = 0x28a7e0
set obj 1 rect from screen 0,0 to screen 1,1 behind
set obj 1 fill solid 1.0 fc rgb ColorScreen
x0=y0=NaN
Derivative(x,y) = (dx=x-x0,x0=x,x-dx/2,dy=y-y0,y0=y,dy/dx) # approx. derivative
# get min/max derivative
set table $Dummy
plot n=0 $Data u (d=abs(Derivative($1,$2)),n=n+1,n<=2? (dmin=dmax=d) : \
(dmin>d ? dmin=d:dmin), (dmax<d?dmax=d:dmax)) w table
unset table
myColor(x,y) = (int((abs(Derivative(column(x),column(y)))-dmin)/(dmax-dmin)*0xff)<<24) +0xffffff
plot $Data u 1:2:(myColor(1,2)) w l lw 1.5 lc rgb var not
### end of code
Result:
In the following Gnuplot:
set xlabel "Network size, m [r]" font " Helvetica,17"
set ylabel "Algorithms computation time [s]" font "Helvetica,17"
$t500 << EOD
1 0 0 0
2 0.00933135 0.0640543 0.215254
3 0.00954345 0.0746418 0.416871
4 0.009779 0.0853093 0.621712
5 0.0101225 0.0958813 0.822831
6 0.0106212 0.106193 1.02248
7 0.0114236 0.11658 1.22483
8 0.0126996 0.128502 1.42843
9 0.0150443 0.138803 1.62994
10 0.0193814 0.149177 1.83284
11 0.0282591 0.159563 2.0358
12 0.0450926 0.170019 2.24009
13 0.0791815 0.180668 2.44586
14 0.146265 0.191207 2.65134
15 0.284757 0.201806 2.85782
16 0.556054 0.212695 3.0671
17 1.11529 0.223592 3.27625
18 2.22795 0.234535 3.4873
19 4.55297 0.245686 3.69976
20 9.02265 0.257064 3.91294
EOD
set key spacing 1.0
set key top left font "Helvetica, 17"
#set xrange [2:20]
#set yrange [0.001:1000]
set logscale y
set grid
set terminal pdfcairo transparent enhanced
set style function filledcurves y1=0
set ytics ("0" 0.001,"0.01" 0.01,"0.1" 0.1,"1" 1,"10" 10,"100" 100)
unset colorbox
set style fill transparent solid 0.2 border
set bmargin 3.5
set out "program500.pdf"
plot [][] '$t500' using 1:2 title 'S computation' w filledcurves lc rgb "forest-green",\
'$t500' using 1:($2+$3) title 'S computation + Stability computation' w filledcurves lc rgb "violet",\
'$t500' using 1:($2+$4) title 'S computation + Max joint flow computation' w filledcurves lc rgb "gold"
The problem I have is set xrange [2:200] the plot changes and fills the curves upwards, like this,
I would like to know how to keep the filling below the curves as in the first plot with the default ranges and setting xrange [2:20].
"with filledcurves" allows many variants. See the documentation for help filledcurves. The default is with filledcurves closed, which tries to use the points to define a perimeter enclosing a surrounded area. If the curve runs off the edge of the plot, the edges of the plot are used to complete the perimeter. As you found, sometimes the edges chosen by the program are not the ones you wanted.
To control this, use one of the other variants. In this case you probably want with filledcurves y=0, which defines the line at y=0 as part of the perimeter.
... initial lines as above ...
set xrange [2:20]
plot'$t500' using 1:2 title 'S computation' w filledcurves y=0 lc rgb "forest-green",\
'$t500' using 1:($2+$3) title 'S computation + Stability computation' w filledcurves y=0 lc rgb "violet",\
'$t500' using 1:($2+$4) title 'S computation + Max joint flow computation' w filledcurves y=0 lc rgb "gold"