Animation

GnuplotRB is able to create gif animations with several plots given as frames. This may be useful to show how function changes in time.

Examples

Changing heatmap
In [1]:
require 'gnuplotrb'
include GnuplotRB
include Math

def generate_heatmaps(initial)
  initial.map do
    Splot.new(
      [initial.shuffle, matrix: true],
      pm3d: ['map', interpolate: [8, 8]],
      palette: 'grey'
    )
  end
end

initial_heatmap = [
  [6, 5, 4, 3, 1, 0],
  [3, 2, 2, 0, 0, 1],
  [0, 0, 0, 0, 1, 0],
  [0, 0, 0, 0, 2, 3],
  [0, 0, 1, 2, 4, 3],
  [0, 1, 2, 3, 4, 5],
]

Animation.new(*generate_heatmaps(initial_heatmap), animate: { delay: 30 })
Out[1]:
Periodic function
In [2]:
def periodic_plots
  count = 100
  timestep = 2 * PI / count
  count.times.map do |i|
    angle = i * timestep
    Plot.new(["sin(x * 30 - 10 * #{angle}) * exp(-abs(x + 2 * sin(#{angle})))", title: 'Moving sinx'])
  end
end

Animation.new(*periodic_plots, xrange: -5..5, yrange: -2..2, samples: 1000)
Out[2]:
Trajectory plots
In [3]:
G = -9.8

def generate_plots(initial, count, time)
  timestep = time.to_f / count
  xx = []
  yy = []
  vx = []
  vy = []
  tt = []
  x_extremum = [
    initial[:position][0] + initial[:velocity][0] * time,
    initial[:position][0]
  ]
  y_extremum = [
    initial[:position][1] + initial[:velocity][1] * time + (G * time ** 2) / 2,
    initial[:position][1]
  ]
  if initial[:velocity][1] < time * G.abs && initial[:velocity][1] > 0
    y_extremum << initial[:position][1] + (initial[:velocity][1] ** 2) / (2 * G).abs
  end
  v_extremum = [
    (initial[:velocity][1] + time * G).abs,
    initial[:velocity][0].abs,
    initial[:velocity][1].abs
  ]
  max_x = x_extremum.max
  min_x = x_extremum.min
  max_y = y_extremum.max
  min_y = y_extremum.min
  min_v = 0
  max_v = v_extremum.max
  min_t = 0
  max_t = time
  count.times.map do |i|
    t = i * timestep
    tt << t
    xx << initial[:position][0] + initial[:velocity][0] * t
    yy << initial[:position][1] + initial[:velocity][1] * t + (G * t ** 2) / 2
    vx << (initial[:velocity][0]).abs
    vy << (initial[:velocity][1] + G * t).abs
    trajectory = Plot.new(
      [[xx, yy], with: 'lines', lw: 2, title: "Object's trajectory"],
      [[[xx.last], [yy.last]], pointtype: 7, pointsize: 2, title: 'Object'],
      xrange: min_x..max_x,
      yrange: min_y..max_y,
    )
    velocity = Plot.new(
      [[tt, vx], with: 'lines', title: "Velocity (x)"],
      [[tt, vy], with: 'lines', title: "Velocity (y)"],
      xrange: min_t..max_t,
      yrange: min_v..max_v,
    )
    Multiplot.new(trajectory, velocity, layout: [2, 1])
  end
end

initial = {
  position: [-10.0, 3.0],
  velocity: [1.0, 3.0]
}

plots = generate_plots(initial, 100, 1)

trajectory = Animation.new(*plots)
Out[3]:
Specific options

Animations has many specific options which you can find in Gnuplot's documentation (in section about gif terminal). Mostly used in GnuplotRB are:

  • animate (with suboptions delay and loop)
  • size
  • background

So lets change delay of previous animation and enlarge the plot.

In [5]:
trajectory.options(animate: {delay: 20, loop: 1}, size: [640, 800], background: '#EDE8FF')
Out[5]: