1 # Animation of BK-pad output
3 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.
5 ## Outline of how it function
7 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".
12 * The velocity if run with "-friction" flag shifts when the first data point for that velocity hits the right side of the screen.
16 * Send in one single array and plot the data
17 * Send in two arrays and plot
20 * Specify/tune these parameters
21 * plot_size - amount of data points plotted per frame
22 * movement_per_frame - amount of data points moved(forward or backward) per frame
23 * n_frames - how many frames in the movie
24 * fps - frames per second
25 * sleep_amount - how long should each frame be shown
26 * Record and save movies
28 * Using list to transport data of what is plotted in each subplot
29 * Support for different amount of lines in each.
31 ### Run animation demo
33 A demo is provided in demo_bk_bkp_animation and demo_pos_pos_spr_friction and can be run with
35 $ python3 src/python/Stricter/Animation/demo_bk_bkp_animation.py
37 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**.
40 #### Code for demo_animation_layout
43 def pos_pos_spr_friction(
46 shift_amount_per_frame=1,
49 sample_range=[0, 2*100],
52 phase_data_block = load_friction_phase_data(run_name,
53 "block_phase_" + str(velocity_index))
54 phase_data_pad = load_friction_phase_data(run_name,
55 "pad_phase_" + str(velocity_index))
56 frames_per_velocity = phase_data_block.shape[1]
57 velocities = loadYaml(run_name,
58 "/results/friction_phase/increment_run.yaml")["velocities"]
59 for i in range(velocity_index + 1, len(velocities)):
60 phase_data_block = np.concatenate((phase_data_block, load_friction_phase_data(run_name, "block_phase_" + str(i))), axis=1)
61 phase_data_pad = np.concatenate((phase_data_pad, load_friction_phase_data(run_name, "pad_phase_" + str(i))), axis=1)
63 position_data, velocity_data = seperate_pos_vel_data(phase_data_block)
64 if("--nopad" in sys.argv):
65 phase_shape_block = phase_data_block.shape
66 block_average = np.zeros(phase_shape_block[1])
67 number_of_blocks = int(phase_shape_block[0]/2)
68 for i in range(0, number_of_blocks):
69 block_average += phase_data_block[2*i]
70 position_data_pad = block_average/number_of_blocks
72 position_data_pad_title = "Block avg. position"
73 position_data_pad_y_label = "$\\frac{\sum_1^n u_i}{n}$"
75 index_first_spring = 1
77 position_data_pad = phase_data_pad[0]
78 position_data_pad_title = "Pad position"
79 position_data_pad_y_label = "$x$"
81 index_first_spring = 3
83 number_of_data_points = len(position_data[0])
84 if(frames > number_of_data_points):
85 frames = number_of_data_points
87 position_plot = make_single_line_line_plot(position_data,
92 x_label="Time steps shown",
95 bar_plot = make_single_line_bar_plot(position_plot,
101 position_pad_plot = make_single_line_line_plot([position_data_pad],
106 x_label="Time steps shown",
107 y_label=position_data_pad_y_label)
109 spring_plot = make_single_line_spring_plot(position_plot,
112 common_indexes=shown_indexes,
113 pad_position=position_data_pad,
117 animation_plots = [position_plot, bar_plot, position_pad_plot, spring_plot]
119 bk_animation = BKAnimation(animation_plots, sleep_amount=0.000, max_lim_change=0.3)
120 bk_animation.init_live_plot((231, 232, 233, 212),
122 ["Position", "Bar", position_data_pad_title, "Spring"],
123 show_plot=live_plotting,
124 suptitle="Velocity: " + str(velocities[velocity_index]))
127 plot_shape = [len(animation_plots), len(position_plot.single_line_list)]
128 only_shift_first = False ones
129 only_shift_first_index = number_of_data_points - shown_indexes[1] - 1
130 def init_plot_frames():
131 bk_animation.update_subplots(update_lims=False)
133 nonlocal velocity_index, only_shift_first
134 bk_animation.update_suptitle("Velocity: %(velocity)1.3f |\
135 Frame: %(frame)i" % {'velocity': velocities[velocity_index],
137 if(n % frames_per_velocity == 0 and n > 0):
140 if(n % only_shift_first_index == 0 and n > 0):
141 only_shift_first = True
142 shift_z_indexes_of_lines_in_ax(bk_animation,
143 shift_amount_per_frame,
145 n_line_number=plot_shape[1],
147 only_shift_first=only_shift_first)
148 shift_z_indexes_of_lines_in_ax(bk_animation,
149 shift_amount_per_frame,
153 only_shift_first=only_shift_first)
155 bk_animation.change_y(1, 0)
156 bk_animation.change_x(3, 0, get_axis="y")
158 bk_animation.change_x(3, 1)
159 bk_animation.update_upper_springs(3, index_first_spring=index_first_spring)
161 bk_animation.update_subplots()
162 sleep(bk_animation.sleep_amount)
166 for i in range(0, frames):
169 ani = animation.FuncAnimation(bk_animation.fig,
171 init_func=init_plot_frames,
174 writer = animation.writers['ffmpeg'](fps=20)
175 simulation_path = loader.get_simulation_path(run_name)
176 ani.save(simulation_path + '/animation_vid_7.mp4',
184 flags = {"no_pad": "--nopad"}
185 live_plotting = False
187 if(demo_number == 1):
188 shown_indexes = [0, 100]
189 run_name = "demo/bk_decrease_seed_106"
190 sys.argv.append(flags["no_pad"])
191 print("You have chosen to run a demo of the Burridge-Knopoff model.",
193 "This data for this run starts at a velocity og 1.49 and down",
195 "to 0.0. Only a sample is plotted.",
197 "The run will start in approximately 10 seconds.")
199 pos_pos_spr_friction(run_name, shown_indexes)
202 if __name__ == "__main__":
203 valid_demo_numbers = ["1"]
204 if(len(sys.argv) == 2):
205 if(sys.argv[1] in valid_demo_numbers):
206 run_demo(int(sys.argv[1]))
208 demo_number = input("Please enter 1 for a demo and anything else to quit: ")
209 if(demo_number in valid_demo_numbers):
210 run_demo(int(demo_number))
213 ### Documentation of classes
215 There are threes classes that are involved when making a live or movie plot. They are
221 , 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.
226 * frame_interval = 10,
227 * movement_per_frame = 10,
232 The values set are defaults that are overrided when set.
237 * Constructur, possible to set above variables when initiating
238 * ```bk_animation = BKAnimation([single_plot, single_plot_2])```
240 * initialize figure and setup specified figures
241 * ```bk_animation.init_live_plot((211, 212), (20,20))```
243 * sets up each of the subplots
244 * init_specified_subplot
245 * sets up each line in a subplot
247 * call after updating values in a plot
248 * update_specified_plots
249 * update each og the lines in a subplot
251 * updates specific values in a line
261 * single_line_list = []
268 * ```single_plot = SinglePlot(ax_number = 0)```
269 * ```single_plot = SinglePlot(ax_number = 1,single_line_list = [single_line])```
271 * append a SingleLine object ot the SinglePlot
291 * ```single_line = SingleLine(x_values, y_values, x_indexes = [0,100], y_indexes = [0,100], ax_number= 0, line_number = 0 )```
292 * Note: x_values and y_valeus must be of the same size
294 * prints current variable values