How to animate multiple points (planets) using gnuplot, from a single data file. - animation

I'm trying to make an animation of Jupiter, the sun and an asteroid at the stable Lagrange point L5 as they orbit around their center of mass. I want to do this animation using gnuplot.
I have written a programme which finds their positions at time t/AU. The data I get is below, has columns, time, x position, y position, and has rows, planet, sun, asteroid. I have looked at other solutions to animating in gnuplot but they do not seem to work for me. Please help me understand what I need to type into the gnuplot command line to get an animation of this data please.
Thank you.
0 0 5.19481
0 0 -0.00519481
0 4.50634 2.6
0.01 0.0275397 5.19473
0.01 -2.75397e-05 -0.00519473
0.01 4.52006 2.57607
0.02 0.0550786 5.19451
0.02 -5.50786e-05 -0.00519451
0.02 4.53365 2.55208
0.03 0.082616 5.19415
0.03 -8.2616e-05 -0.00519415
0.03 4.54712 2.52801
0.04 0.110151 5.19364
0.04 -0.000110151 -0.00519364
0.04 4.56046 2.50386
0.05 0.137683 5.19298
0.05 -0.000137683 -0.00519298
0.05 4.57367 2.47965
0.06 0.165211 5.19218
0.06 -0.000165211 -0.00519218
0.06 4.58675 2.45537
etc...

This is just a draft:
stats 'test.txt' u 2:3
set xr [STATS_min_x:STATS_max_x]
set yr [STATS_min_y:STATS_max_y]
do for [i=0:STATS_blocks-1] {
plot 'test.txt' index i u 2:3 w p pt 7 title sprintf("time: %f",i*0.01)
pause 1
}
you can directly create an animated gif:
stats 'test.txt' u 2:3
set xr [STATS_min_x:STATS_max_x]
set yr [STATS_min_y:STATS_max_y]
set term gif animate
set output 'test.gif'
do for [i=0:STATS_blocks-1] {
plot 'test.txt' index i u 2:3 w p pt 7 title sprintf("time: %f",i*0.01)
}
Now this is quite basic, but can be tuned to make really high quality images.

Related

How to sort for most negative values and most positive values across columns?

I am trying to create a new column in my dataframe based on the maximum values across 3 columns. However, depending on the values within each row, I want it to sort for either the most negative value or the most positive value. If the average for an individual row across the 3 columns is greater than 0, I want it to report the most positive value. If it is less than 0, I want it to report back the most negative value.
Here is an example of the dataframe
A B C
-0.30 -0.45 -0.25
0.25 0.43 0.21
-0.10 0.10 0.25
-0.30 -0.10 0.05
And here is the desired output
A B C D
-0.30 -0.45 -0.25 -0.45
0.25 0.43 0.21 0.43
-0.10 0.10 0.25 0.25
-0.30 -0.10 0.05 -0.30
I had first tried playing around with something like
data %>%
mutate(D = pmax(abs(A), abs(B), abs(C)))
But that just returns a column with the greatest of the absolute values where everything is positive.
Thanks in advance for your help, and apologies if the formatting of the question is off, I don't use this site a lot. Happy to clarify anything as well.

gnuplot: interactive 3D animations?

With gnuplot you can create a 3D-like plot with splot and interactively change the view.
You also can create animations with gnuplot with set terminal gif animate.
### interactive animation?
reset session
set view equal
set border 0
unset tics
$Data <<EOD
1 1.000 0.000 0.000
2 0.500 0.866 0.000
3 -0.500 0.866 0.000
4 -1.000 0.000 0.000
5 -0.500 -0.866 0.000
6 0.500 -0.866 0.000
1 1.000 0.000 0.000
EOD
$Off <<EOD
1 0.00 0.00 0.1
2 0.00 0.00 -0.1
3 0.00 0.00 0.1
4 0.00 0.00 -0.1
5 0.00 0.00 0.1
6 0.00 0.00 -0.1
1 0.00 0.00 0.1
EOD
set xrange[-2:2]
set yrange[-2:2]
set zrange[-2:2]
set view 45,45
max=10.
Offset(n,axis,i) = real(word($Off[n+1],axis+1))*sin(2*pi*i/max)
set term gif animate delay 5 size 400,300
set output "Molecule.gif"
do for [i=0:max] {
splot $Data u ($2+Offset($0,1,i)):($3+Offset($0,2,i)):($4+Offset($0,3,i)) \
w lp pt 7 ps 2 lw 2 lc rgb "red" not
unset autoscale
}
set term wxt size 400,300
set margin 0
splot $Data u 2:3:4 w lp pt 7 ps 2 lw 2 lc rgb "red" not
set output
### end of code
Now, my question is: is there maybe the chance to also create interactive animations? I would like to rotate the view while it is animated. Is this somehow possible with gnuplot? Any ideas?
Edit:
#Ethan's answer solves this question. However, is there maybe a way to avoid the flickering of the mouse cursor?
Putting the plot commands in a loop does not disable mouse interaction. The simple answer should work:
set xrange[-2:2]
set yrange[-2:2]
set zrange[-2:2]
set view 45,45
Offset(n,axis,i) = real(word($Off[n+1],axis+1))*sin(2*pi*i/max)
# Loop forever
# but allow an explicit end condition triggered by a hot key
done = 0
bind "d" "done = 1"
while (!done) {
do for [i=0:10] {
splot $Data u ($2+Offset($0,1,i)):($3+Offset($0,2,i)):($4+Offset($0,3,i)) \
w lp pt 7 ps 2 lw 2 lc rgb "red" not
pause 0.1
}
}

Algorithm for optimal expected amount in a profit/loss game

I came upon the following question recently,
"You have a box which has G green and B blue coins. Pick a random coin, G gives a profit of +1 and blue a loss of -1. If you play optimally what is the expected profit."
I was thinking of using a brute force algorithm where I consider all possibilities of combinations of green and blue coins but I'm sure there must be a better solution for this (range of B and G was from 0 to 5000). Also what does playing optimally mean? Does it mean that if i pick all blue coins then I would continue playing till all green coins are also picked? If so then this means I shouldn't consider all possibilities of green and blue coins?
The "obvious" answer is to play whenever there's more green coins than blue coins. In fact, this is wrong. For example, if there's 999 green coins and 1000 blue coins, here's a strategy that takes an expected profit:
Take 2 coins
If GG -- stop with a profit of 2
if BG or GB -- stop with a profit of 0
if BB -- take all the remaining coins for a profit of -1
Since the first and last possibilities both occur with near 25% probability, your overall expectation is approximately 0.25*2 - 0.25*1 = 0.25
This is just a simple strategy in one extreme example that shows that the problem is not as simple as it first seems.
In general, the expectations with g green coins and b blue coins is given by a recurrence relation:
E(g, 0) = g
E(0, b) = 0
E(g, b) = max(0, g(E(g-1, b) + 1)/(b+g) + b(E(g, b-1) - 1)/(b+g))
The max in the final row occurs because if it's -EV to play, then you're better stopping.
These recurrence relations can be solved using dynamic programming in O(gb) time.
from fractions import Fraction as F
def gb(G, B):
E = [[F(0, 1)] * (B+1) for _ in xrange(G+1)]
for g in xrange(G+1):
E[g][0] = F(g, 1)
for b in xrange(1, B+1):
for g in xrange(1, G+1):
E[g][b] = max(0, (g * (E[g-1][b]+1) + b * (E[g][b-1]-1)) * F(1, (b+g)))
for row in E:
for v in row:
print '%5.2f' % v,
print
print
return E[G][B]
print gb(8, 10)
Output:
0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
1.00 0.50 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
2.00 1.33 0.67 0.20 0.00 0.00 0.00 0.00 0.00 0.00 0.00
3.00 2.25 1.50 0.85 0.34 0.00 0.00 0.00 0.00 0.00 0.00
4.00 3.20 2.40 1.66 1.00 0.44 0.07 0.00 0.00 0.00 0.00
5.00 4.17 3.33 2.54 1.79 1.12 0.55 0.15 0.00 0.00 0.00
6.00 5.14 4.29 3.45 2.66 1.91 1.23 0.66 0.23 0.00 0.00
7.00 6.12 5.25 4.39 3.56 2.76 2.01 1.34 0.75 0.30 0.00
8.00 7.11 6.22 5.35 4.49 3.66 2.86 2.11 1.43 0.84 0.36
7793/21879
From this you can see that the expectation is positive to play with 8 green and 10 blue coins (EV=7793/21879 ~= 0.36), and you even have positive expectation with 2 green and 3 blue coins (EV=0.2)
Simple and intuitive answer:
you should start off with an estimate for the total number of blue and green coins. After each pick you will update this estimate. If you estimate there are more blue coins than green coins at any point you should stop.
Example:
you start and you pick a coin. Its green so you estimate 100% of the coins are green. You pick a blue so you estimate 50% of coins are green. You pick another blue coin so you estimate 33% of the coins are green. At this point is isn't worth playing anymore, according to your estimate, so you stop.
This answer is wrong; see Paul Hankin's answer for counterexamples and a proper analysis. I leave this answer here as a learning example for all of us.
Assuming that your choice is only when to stop picking coins, you continue as long as G > B. That part is simple. If you start with G < B, then you never start drawing, and your gain is 0. For G = B, no strategy will get you a mathematical advantage; the gain there is also 0.
For the expected reward, take this in two steps:
(1) Expected value on any draw sequence. Do this recursively, figuring the chance of getting green or blue on the first draw, and then the expected values for the new state (G-1, B) or (G, B-1). You will quickly see that the expected value of any given draw number (such as all possibilities for the 3rd draw) is the same as the original.
Therefore, your expected value on any draw is e = (G-B) / (G+B). Your overall expected value is e * d, where d is the number of draws you choose.
(2) What is the expected number of draws? How many times do you expect to draw before G = B? I'll leave this as an exercise for the student, but note the previous idea of doing this recursively. You might find it easier to describe the state of the game as (extra, total), where extra = G-B and total = G+B.
Illustrative exercise: given G=4, B=2, what is the chance that you'll draw GG on the first two draws (and then stop the game)? What is the gain from that? How does that compare with the (4-2)/(4+2) advantage on each draw?

Add axes label to pcolor image

I created a pcolor image with each grid shaded in based on a value in the matrix C.
h1 = pcolor(C);
colormap(jet)
h = colorbar;
ylabel(h,'Monthly Correlation (r-value)');
shading flat
Each grid corresponds to a particular year on the x axes and a particular site name on the y axes. How can I add an axes label to show this?
I tried the following but it didn't do anything. Plus, I'd like to put the label in the middle of each grid, not on the edges.
set(h1,'XTick',years')
set(h1,'YTick',a)
x axes labels: years' looks like this (size 15x1 double)
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
y axes labels: a looks like this (12x1 cell):
'09-003-1003-88101'
'09-009-0027-88101'
'25-013-0008-88101'
'25-025-0042-88101'
'33-005-0007-88101'
'33-009-0010-88101'
'33-011-5001-88101'
'33-015-0014-88101'
'33-015-0018-88101'
'44-003-0002-88101'
'44-007-1010-88101'
'44-009-0007-88101'
Current image looks like this:
You are using the wrong handle. For setting labels you need the axes handle and not the pcolor-handle:
%// get axes handle
ax = gca;
...
%// set labels
set(ax,'XTickLabel',years')
set(ax,'YTickLabel',a)
Example:
%// example data
C = [...
0.06 -0.22 -0.10 0.68 NaN -0.33;
0.04 -0.07 0.12 0.23 NaN -0.47;
NaN NaN NaN NaN NaN 0.28;
0.37 0.36 0.14 0.58 -0.14 -0.15;
NaN 0.11 0.24 0.71 -0.13 NaN;
0.57 0.53 0.41 0.65 -0.43 0.03 ];
%// original plot
h1 = pcolor(C);
colormap(jet)
h = colorbar;
ylabel(h,'Monthly Correlation (r-value)');
shading flat
%// get axes handle
ax = gca;
%// labels (shortened to fit data)
years = [1999, 2000, 2001, 2002, 2003, 2004];
a = {'09-003-1003-88101', '09-009-0027-88101', '25-013-0008-88101', ...
'25-025-0042-88101', '33-005-0007-88101', '33-009-0010-88101'};
%// adjust position of ticks
set(ax,'XTick', (1:size(C,2))+0.5 )
set(ax,'YTick', (1:size(C,1))+0.5 )
%// set labels
set(ax,'XTickLabel',years')
set(ax,'YTickLabel',a)

Multiple palettes and empty labels from file entries using matrix with image in gnuplot

I have a file with a 4x4 score matrix and I'd like to plot the upper triangular with one color palette and the lower triangular with a different one, overlaying the score value (MWE at the bottom).
The original file looks like this
0.00 0.65 0.65 0.25
0.25 0.00 0.75 0.25
0.50 0.60 0.00 0.25
0.75 0.25 0.10 0.00
First, I created two separate files and used multiplot to have 2 different palettes.
FILE1 (upper triangular)
0.00 0.65 0.65 0.25
nan 0.00 0.75 0.25
nan nan 0.00 0.25
nan nan nan 0.00
FILE2 (lower triangular)
0.00 nan nan nan
0.25 0.00 nan nan
0.50 0.60 0.00 nan
0.75 0.25 0.10 0.00
Second, I plot the score values with
using 1:2:( sprintf('%.2f', $3 ) )
However, the 'nan' isn't interpreted as blank/empty and skipped but written onto the plot.
Any idea how to skip the nans and make gnuplot plot empty labels from individual entries of the data files?
The ternary operator in the following fashion do not seem to do the job
using 1:2:( $3 == 'nan' ? 1/0 : sprintf('%.2f', $3 ))
Thanks.
set multiplot
set autoscale fix
unset key
set datafile missing "nan"
set cbrange [0:1]
unset colorbox
set palette defined (0 "white", 0.1 "#9ecae1", 1.0 "#3182bd")
plot FILE1 matrix with image, \
FILE1 matrix using 1:2:( sprintf('%.2f', $3) ) with labels font ',16'
set palette defined (0 "white", 0.1 "#a1d99b", 1.0 "#31a354")
plot FILE2 matrix with image, \
FILE2 matrix using 1:2:( sprintf('%.2f', $3) ) with labels font ',16'
unset multiplot
You don't need to use multiplot and two separate files (I also couldn't get this working with the labels).
Just define a single palette, which contains as negative values one palette and as positive values the other palette. Based on the x and y-value from the single file you show first, you can now distinguish if the color value should be taken from the negative or from the positive palette part:
set autoscale fix
set cbrange [-1:1]
unset colorbox
unset key
set palette defined (-1.0 "#31a354", -0.1 "#a1d99b", 0 "white", 0.1 "#9ecae1", 1.0 "#3182bd")
plot 'FILE' matrix using 1:2:($1<$2 ? -$3 : $3) with image,\
'' matrix using 1:2:(sprintf('%.2f', $3)) with labels font ',16'

Resources