gnuplot animation 2D vector fields - animation

I'm trying to animate 2D vector with gnuplot. I want to show one line i.e, one vector at a time.
My Data Structure is as follows: They x,y,u,v
2.24448 0.270645 1.00 1.00
3.24448 0.270645 0.500 1.20
I'm able to create a static plot sing following command:
plot "datam.dat" using 1:2:3:4 with vectors filled head lw 3
Here is the output:
Here is my question: I would like to animate and show one row (i.e,) one vector at a time, how to accomplish this in GNU plot using GIF?
Thanks

Animated GIFs are created with set terminal gif animate. Check help gif for details.
Below is a simple example (tested with gnuplot 5.2). You have to make a new plot for each frame. So, put your plot command into a do for-loop. With every ::i::i you are plotting only the ith line (check help every). If you don't know the total number of lines of your datafile, do stats "YourFile.dat" and the variable STATS_records will tell you this number.
Code:
### animated graph with vectors
reset session
set term gif size 300,300 animate delay 12 loop 0 optimize
set output "AnimateVectors.gif"
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
do for [i=0:N-1] {
plot $Data u 1:2:3:4 every ::i::i w vectors lw 2 lc rgb "red" notitle
}
set output
### end of code
Result:
Addition:
This would be the non-animated version, e.g. in a wxt-terminal.
Code:
### non-animated graph with vectors
reset session
set term wxt size 400,400
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
plot $Data u 1:2:3:4 w vectors lw 1.5 lc rgb "red" notitle
### end of code
Result:
Addition2:
Do you maybe mean something like this? A "semi"-animated arrow? By the way, as you can see the arrow look quite different in gif and wxt terminal.
Code:
### "semi"-animated graph with vectors
reset session
set term gif size 300,300 animate delay 12 loop 0 optimize
set output "AnimateVectorsSemi.gif"
# create some dummy data
set angle degrees
N = 60
set samples N
set table $Data
plot [0:360] '+' u (cos($1)):(sin($1)):(sin($1)):(cos($1)) w table
unset table
set xrange[-2.5:2.5]
set yrange[-2.5:2.5]
do for [i=0:N-1] {
plot $Data u 1:2:3:4 every ::0::i w vectors lw 1.5 lc rgb "red" notitle
}
set output
### end of code
Result:

Related

How to add time dependent labels in Gnuplot

A datafile contains three columns with the first and second representing the x & y position of a circle at a time (in seconds) given by the third column. For example, the first two lines in "data.txt" give the position of two circles at time=0, followed by two blank lines then the position of the two circles at time=0.1 sec and so forth. The first few lines of data.txt are:
0 0 0
-1 -1 0
1 1.0 0.1
-1 -0.5 0.1
1.2 1.25 0.2
-0.5 -0.25 0.2
...
The Gnuplot code producing a series of frames (a movie) with the position of the two circles in time is:
set terminal gif size 1200,1200 animate delay 500
set output "movie.gif"
stats "data.txt" u 1:2 name "A"
set style circle radius graph 0.025; set style fill solid
set xrange [A_min_x*1.1:A_max_x*1.1]
set yrange [A_min_y*1.1:A_max_y*1.1]
do for [i=0:A_blocks-2] {
plot "data.txt" index i u 1:2 w circle
}
I'm trying to add a label or textbox of the form "Time=?" to each frame where the question mark is replaced by the number from the third column. Any suggestions on how to do it?
This answer requires the current version of gnuplot (5.4)
Assuming that all the column 3 entries in a given data block are the same, it should be sufficient to say
plot "data.txt" index i u 1:(FOO=strcol(3),column(2)) w circle title sprintf("Time = %s",FOO)
This updates the value of FOO for each line used. The title uses whatever the final update was for that plot. If you must specifically choose the column 3 value from a particular line within the block, or calculate something like an average, that's a harder problem. In that case please clarify.
Edit:
The reason this requires 5.4 is that earlier versions evaluated the title before reading the data for that plot. Version 5.4 evaluates the title after reading the data.
The first (not too obvious) solution which comes to my mind: plot your data in a loop and assign the value of the 3rd column to a variable, e.g. t. Use keyenty to print the legend with your time re-using the variable t. In order to avoid a symbol in the legend use plotting style with points and a point with pointsize 0.
Code:
### animation with time label
reset session
$Data <<EOD
0 0 0
-1 -1 0
1 1.0 0.1
-1 -0.5 0.1
1.2 1.25 0.2
-0.5 -0.25 0.2
EOD
set terminal gif size 400,400 animate delay 100
set output "SO70474478.gif"
stats $Data u 1:2 name "A" nooutput
set style circle radius graph 0.025; set style fill solid
set xrange [A_min_x*1.1:A_max_x*1.1]
set yrange [A_min_y*1.1:A_max_y*1.1]
set key top left
do for [i=0:A_blocks-1] {
plot $Data index i u 1:(t=$3,$2) w circle notitle, \
keyentry w points ps 0 ti sprintf("Time: %.1f",t)
}
set output
### end of code
Result:

gnuplot: compact axis label format

Tell me how in gnuplot to properly form the inscriptions in the axis (as shown in the picture).
1) I do not know the values of the y axis
2) I need to set the exponent (power 10) in the axis label automatically
You need to know the order of magnitude before you are plotting. You can get this via stats. Then divide your y-values by a factor which (in the example below) is chosen such that the axis tics should show values between 0 and 100.
The code:
### automatic prefactor in axis scaling and axis label
reset session
# generate some random data
set samples 20
RandomMagnitude = floor(rand(0)*20-10)
RandomValue = rand(0)
set table $Data
plot '+' u 0:(RandomValue*10**RandomMagnitude/($0)) with table
unset table
# get the maximum via stats
stats $Data u 2 nooutput
Max = STATS_max
PrefactorLog = ceil(log10(Max))-2
Prefactor = 10**PrefactorLog
set ylabel sprintf("Y-title, x 10^{%d} units",PrefactorLog)
set format y "%g"
set boxwidth 0.7 relative
plot $Data u 1:($2/Prefactor) with boxes fs solid 1.0 fc rgb "red" ti sprintf("Max value %.2e", Max)
### end of code
The result:

How to make a 2D gnuplot animation using matrix nonuniform data file format?

I want to know how to make a Gnuplot 2d animation using the gnuplot matrix non uniform format, with the first column being the time, the first row being the x axis ticks and the first number of the first row being the number of columns after the first one, an example of such a matrix is given by, imagine we have 2 time iterations and 2 space points. If the index goes from 0 to 1 then,such matrix would be like this
2 x[0] x[1]
t[0] f(0,0) f(0,1)
t[1] f(1,0) f(1,1)
How to make a 2d animation in gnuplot for f(t,x) for each time iteration?
Thanks
it probably might be easier if your data looked the following way:
2x2 t[0] t[1]
x[0] f(0,0) f(0,1)
x[1] f(1,0) f(1,1)
If your data already exists with columns x[..] and rows t[..] there is probably also a way to do it, but probably a bit more complicated.
The following example will create some dummy data (writes it also into a file) and will plot it into an animated GIF. In gnuplot, also check help gif for more information. Change the code to your needs.
### create some animated graph
reset session
set term gif size 300,300 animate delay 10 loop 0 optimize
set output "Animate.gif"
# create some dummy data
m = 50
n = 50
set print $Data
temp = sprintf("%gx%g\t",m,n)
do for [j=1:n] {
temp = temp.sprintf("t[%g]",j)
if (j<n) {temp = temp."\t"}
}
print temp
do for [i=1:m] {
temp = ""
do for [j=1:n] {
temp = temp.sprintf("%g", sin(2*pi*j/real(n)+2*pi*i/real(m)))
if (j<n) {temp = temp."\t"}
}
temp = sprintf("x[%g]\t",i).temp
print temp
}
set print "Animate.dat"
print $Data
set print
# dummy data finished
FILE = "Animate.dat"
stats FILE u 0 nooutput
set yrange[-1:1]
set xtics 10
set grid xtics, ytics
do for [i=2:STATS_columns] {
plot FILE u 0:i w lp lt 7 lc rgb "red" title columnhead(i)
}
set output
### end code

Gnuplot--set label for points that exceed data range

My question about how to automate placing labels at the edge of a plot for data points that exceed the range of plot. This would be done for points that are outliers that, if plotted, skew the scale of the plot such that the plot is no longer useful, but still need to be noted.
For example, let's say I've got a data file called 'mydata.dat' that looks like this:
1 2
3 3
7 4
8 6
50 8
If I plot the data using
set yrange [0:10]
set xrange [0:10]
plot 'mydata.dat' w lp pt 1
then the last point (50,8) will not be plotted. To acknowledge, however, that there is a point outside the plotted range, a label and point would be placed at the edge (i.e., at 10,8) of the plot using
set label "" at 10,8 point pt 1
set label "50" at 9.75,8 right
Is there a way to automate this process? A way to have GNUplot read the entire data file and set points and labels at the edge of the plot?
To plot all point which are outside of the specified range, you'll need a second plot command using the labels plotting style.
In the using statement you can then check for the point being outside the range. If it is, you place a point with a corresponding label, otherwise you skip the point (using 1/0 as value):
set xrange [0:10]
set yrange [0:10]
set linetype 1 pt 7
plot 'mydata.dat' w lp lt 1, \
'' using ($1 > 10 ? 10 : 1/0):2:(sprintf('%d', $1)) with labels right offset -2,-0.25 point lt 1 notitle
Here, I check only for the x-value being larger than the specified maximum x-value. Maybe you need to adapt it in order to catch also outliers in y-direction or those smaller than 0.

how can I create an animated, labeled point following a trajectory in gnuplot?

After quite a bit of tweaking to an existing GNU plot, I managed to get the following:
reset
# png
set terminal png size 350,262 enhanced font 'Verdana,10'
# color definitions
set style line 1 lc rgb '#0060ad' lt 1 lw 2 pt 7 ps 2 # --- blue
unset key
set border 0
unset tics
# set view 342,0
set xrange [-300:300]
set yrange [-300:300]
n=0
do for [ii=1:99] {
n=n+1
set output sprintf('png/spiral%03.0f.png',n)
plot '1_1910.txt' every ::1::ii w l ls 1, \
'2_1910.txt' every ::1::ii w l ls 1
}
do for [ii=1:99] {
n=n+1
set output sprintf('png/spiral1%03.0f.png',n)
plot '1_1920.txt' every ::1::ii w l ls 1, \
'2_1920.txt' every ::1::ii w l ls 1
}
The idea is to create a set of PNG files, and then concatenate them all with animation.
I concatenate them all together using
convert -delay 2 -loop 0 png/*.png animation.gif
I want to make more tweaks:
I don't want to keep the line that follows the whole plot (even though animated). Instead, I want a "bullet point" (maybe the size of 5-10 pixels) with text moving next to it for each frame for each data point in the plot.
I want a text at the bottom right for the first set of frames (in the first 1:99 loop) and a different text replacing it, again in the bottom right corner (in the next 1:99 loop).
My code is based on this:
http://www.gnuplotting.org/animation-iv-trajectory/
but I can't figure out why his code has a "trail" that disappears, and why he has also a bullet point and I don't. As I said, I also want text that moves with the bullet point (same text for each data file).
I think you can do it with loops like this:
n = 0
do for [ii=0:60] {
n=n+1
set output sprintf('png/spiral%03.0f.png',n)
plot 'data.dat' every ::ii::ii w p ls 1, \
'data.dat' using 1:2:("foo") every ::ii::ii w labels offset 2
}
set label 1 "hyde" at 275,-275
do for [ii=60:0:-1] {
n=n+1
set output sprintf('png/spiral%03.0f.png',n)
plot 'data.dat' every ::ii::ii w p ls 1, \
'data.dat' using 1:2:("foo") every ::ii::ii w labels offset 2
}
Here is the result:
You can play with the offset coordinates to position the label text "foo" where you want.
To change the size of the point, change the value of ps in the line style command at the beginning of your script.
I am not sure what the purpose of the two different files is (1_1910.txt and 2_1920.txt), so I used the same file in my example. You may need to add to the plot command if you are plotting two different things at once.
As for your other questions, I think looking closely at the code in the example should give you an idea of what is going on. In the example, the range every ::1::ii plots points from 1 to ii, giving a line; the range every ::ii::ii plots just one point. Note that the abbreviations w l and w p in the example expand to with lines and with points, respectively.
In the example the line disappears due to the action of the second loop, which runs in reverse (for [ii=99:1:-1]). If you are copying that example, make sure also that your indices run over the correct values (you may have a number other than 99 of data points). Also note that indices in gnuplot start at 0, so if the first line of your data file contains data (not a header) you want to start your loop at ii=0 instead of ii=1.
I am having nearly the same problem here. I found a really nice hack! Instead of making multiple png's and then merge them, you just use set multiplot and then unset multiplot inside ONE loop. Being specific I used it this way:
do for [i=0:k]
{
set multiplot
plot function1
plot function2
unset multiplot
}
But unfortunately this won't work unless the data set you have is synchronized!, but yet can be solve this using if-statement!. Good Luck

Resources