My Project
Animation of BK-pad output

The goal is to make useful movies of the output of the BK-pad simulations. Looking at a movie can tell some different aspects and properties of the output than still images can. An attempt is made to make the code usable from other classes, as is all of the python code in this project. This seems to always fail somewhat, but this "readme" is an attempt to fail a bit less.

Outline of how it function

During the project there where several layouts developed using the same "animation engine". These are located in "/run_animation_layout.py". This file contain many layouts. Each is contained in a folder with some set configurations to ease the process of running them. The closer to the end of the file a layout is the newer the layout is. Understanding this file can be difficult to understand a demo version is made in "/demo_animation_layout.py".

Animation specific

Specifications

Run animation demo

A demo is provided in demo_bk_bkp_animation and demo_pos_pos_spr_friction and can be run with

$ python3 src/python/Stricter/Animation/demo_bk_bkp_animation.py

and follow the instruction in the command line. The two choice are either the BK or BKP model at slider velocity 0.12. The data used is stored in results/demo.

Code for demo_animation_layout

def pos_pos_spr_friction(
run_name,
shown_indexes,
shift_amount_per_frame=1,
frames=1000,
live_plotting=True,
sample_range=[0, 2*100],
velocity_index=40
):
phase_data_block = load_friction_phase_data(run_name,
"block_phase_" + str(velocity_index))
phase_data_pad = load_friction_phase_data(run_name,
"pad_phase_" + str(velocity_index))
frames_per_velocity = phase_data_block.shape[1]
velocities = loadYaml(run_name,
"/results/friction_phase/increment_run.yaml")["velocities"]
for i in range(velocity_index + 1, len(velocities)):
phase_data_block = np.concatenate((phase_data_block, load_friction_phase_data(run_name, "block_phase_" + str(i))), axis=1)
phase_data_pad = np.concatenate((phase_data_pad, load_friction_phase_data(run_name, "pad_phase_" + str(i))), axis=1)
position_data, velocity_data = seperate_pos_vel_data(phase_data_block)
if("--nopad" in sys.argv):
phase_shape_block = phase_data_block.shape
block_average = np.zeros(phase_shape_block[1])
number_of_blocks = int(phase_shape_block[0]/2)
for i in range(0, number_of_blocks):
block_average += phase_data_block[2*i]
position_data_pad = block_average/number_of_blocks
position_data_pad_title = "Block avg. position"
position_data_pad_y_label = "$\\frac{\sum_1^n u_i}{n}$"
show_pad = False
index_first_spring = 1
else:
position_data_pad = phase_data_pad[0]
position_data_pad_title = "Pad position"
position_data_pad_y_label = "$x$"
show_pad = True
index_first_spring = 3
number_of_data_points = len(position_data[0])
if(frames > number_of_data_points):
frames = number_of_data_points
position_plot = make_single_line_line_plot(position_data,
shown_indexes,
ax_number=0,
y_min=-3.0,
y_max=2.0,
x_label="Time steps shown",
y_label="$u_i$")
bar_plot = make_single_line_bar_plot(position_plot,
ax_number=1,
line_number=0,
x_label="Block",
y_label="$u_i$")
position_pad_plot = make_single_line_line_plot([position_data_pad],
shown_indexes,
ax_number=2,
y_min=-3.0,
y_max=2.0,
x_label="Time steps shown",
y_label=position_data_pad_y_label)
spring_plot = make_single_line_spring_plot(position_plot,
ax_number=3,
line_number=0,
common_indexes=shown_indexes,
pad_position=position_data_pad,
x_label="$x$",
y_label="Model",
show_pad=show_pad)
animation_plots = [position_plot, bar_plot, position_pad_plot, spring_plot]
bk_animation = BKAnimation(animation_plots, sleep_amount=0.000, max_lim_change=0.3)
bk_animation.init_live_plot((231, 232, 233, 212),
(20, 10),
["Position", "Bar", position_data_pad_title, "Spring"],
show_plot=live_plotting,
suptitle="Velocity: " + str(velocities[velocity_index]))
plot_shape = [len(animation_plots), len(position_plot.single_line_list)]
only_shift_first = False ones
only_shift_first_index = number_of_data_points - shown_indexes[1] - 1
def init_plot_frames():
bk_animation.update_subplots(update_lims=False)
def plot_frames(n):
nonlocal velocity_index, only_shift_first
bk_animation.update_suptitle("Velocity: %(velocity)1.3f |\
Frame: %(frame)i" % {'velocity': velocities[velocity_index],
'frame': n})
if(n % frames_per_velocity == 0 and n > 0):
velocity_index += 1
if(n % only_shift_first_index == 0 and n > 0):
only_shift_first = True
shift_z_indexes_of_lines_in_ax(bk_animation,
shift_amount_per_frame,
ax_number=0,
n_line_number=plot_shape[1],
index_type='y',
only_shift_first=only_shift_first)
shift_z_indexes_of_lines_in_ax(bk_animation,
shift_amount_per_frame,
ax_number=2,
n_line_number=1,
index_type='y',
only_shift_first=only_shift_first)
bk_animation.change_y(1, 0)
bk_animation.change_x(3, 0, get_axis="y")
if(show_pad):
bk_animation.change_x(3, 1)
bk_animation.update_upper_springs(3, index_first_spring=index_first_spring)
bk_animation.update_subplots()
sleep(bk_animation.sleep_amount)
if(live_plotting):
init_plot_frames()
for i in range(0, frames):
plot_frames(i)
else:
ani = animation.FuncAnimation(bk_animation.fig,
plot_frames,
init_func=init_plot_frames,
frames=frames,
interval=30)
writer = animation.writers['ffmpeg'](fps=20)
simulation_path = loader.get_simulation_path(run_name)
ani.save(simulation_path + '/animation_vid_7.mp4',
writer=writer,
dpi=100)
def run_demo(
demo_number
):
flags = {"no_pad": "--nopad"}
live_plotting = False
sample_mode = False
if(demo_number == 1):
shown_indexes = [0, 100]
run_name = "demo/bk_decrease_seed_106"
sys.argv.append(flags["no_pad"])
print("You have chosen to run a demo of the Burridge-Knopoff model.",
"\n"
"This data for this run starts at a velocity og 1.49 and down",
"\n",
"to 0.0. Only a sample is plotted.",
"\n",
"The run will start in approximately 10 seconds.")
sleep(8)
pos_pos_spr_friction(run_name, shown_indexes)
if __name__ == "__main__":
valid_demo_numbers = ["1"]
if(len(sys.argv) == 2):
if(sys.argv[1] in valid_demo_numbers):
run_demo(int(sys.argv[1]))
else:
demo_number = input("Please enter 1 for a demo and anything else to quit: ")
if(demo_number in valid_demo_numbers):
run_demo(int(demo_number))

Documentation of classes

There are threes classes that are involved when making a live or movie plot. They are

  1. BKAnimation
  2. SinglePlot
  3. SingleLine

, where BKAnimation contains a main figure with subplots stored in SinglePlot instances that again contains lineplots stored in SingleLine instances. Below is a description of all the classes.

BKAnimation

The values set are defaults that are overrided when set.

key functions:

SinglePlot

Contains:

key functions:

SingleLine

Contains:

key functions: