My Project
src/python/Stricter/Animation/readme.md
Go to the documentation of this file.
1 # Animation of BK-pad output
2 
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.
4 
5 ## Outline of how it function
6 
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".
8 
9 
10 ## Animation specific
11 
12 * The velocity if run with "-friction" flag shifts when the first data point for that velocity hits the right side of the screen.
13 
14 ## Specifications
15 
16 * Send in one single array and plot the data
17 * Send in two arrays and plot
18  * Against each other
19  * In subplots
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
27 * Live plot data
28 * Using list to transport data of what is plotted in each subplot
29  * Support for different amount of lines in each.
30 
31 ### Run animation demo
32 
33 A demo is provided in demo_bk_bkp_animation and demo_pos_pos_spr_friction and can be run with
34 ```
35 $ python3 src/python/Stricter/Animation/demo_bk_bkp_animation.py
36 ```
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**.
38 
39 
40 #### Code for demo_animation_layout
41 
42 ```python
43 def pos_pos_spr_friction(
44  run_name,
45  shown_indexes,
46  shift_amount_per_frame=1,
47  frames=1000,
48  live_plotting=True,
49  sample_range=[0, 2*100],
50  velocity_index=40
51 ):
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)
62 
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
71 
72  position_data_pad_title = "Block avg. position"
73  position_data_pad_y_label = "$\\frac{\sum_1^n u_i}{n}$"
74  show_pad = False
75  index_first_spring = 1
76  else:
77  position_data_pad = phase_data_pad[0]
78  position_data_pad_title = "Pad position"
79  position_data_pad_y_label = "$x$"
80  show_pad = True
81  index_first_spring = 3
82 
83  number_of_data_points = len(position_data[0])
84  if(frames > number_of_data_points):
85  frames = number_of_data_points
86 
87  position_plot = make_single_line_line_plot(position_data,
88  shown_indexes,
89  ax_number=0,
90  y_min=-3.0,
91  y_max=2.0,
92  x_label="Time steps shown",
93  y_label="$u_i$")
94 
95  bar_plot = make_single_line_bar_plot(position_plot,
96  ax_number=1,
97  line_number=0,
98  x_label="Block",
99  y_label="$u_i$")
100 
101  position_pad_plot = make_single_line_line_plot([position_data_pad],
102  shown_indexes,
103  ax_number=2,
104  y_min=-3.0,
105  y_max=2.0,
106  x_label="Time steps shown",
107  y_label=position_data_pad_y_label)
108 
109  spring_plot = make_single_line_spring_plot(position_plot,
110  ax_number=3,
111  line_number=0,
112  common_indexes=shown_indexes,
113  pad_position=position_data_pad,
114  x_label="$x$",
115  y_label="Model",
116  show_pad=show_pad)
117  animation_plots = [position_plot, bar_plot, position_pad_plot, spring_plot]
118 
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),
121  (20, 10),
122  ["Position", "Bar", position_data_pad_title, "Spring"],
123  show_plot=live_plotting,
124  suptitle="Velocity: " + str(velocities[velocity_index]))
125 
126 
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)
132  def plot_frames(n):
133  nonlocal velocity_index, only_shift_first
134  bk_animation.update_suptitle("Velocity: %(velocity)1.3f |\
135  Frame: %(frame)i" % {'velocity': velocities[velocity_index],
136  'frame': n})
137  if(n % frames_per_velocity == 0 and n > 0):
138  velocity_index += 1
139 
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,
144  ax_number=0,
145  n_line_number=plot_shape[1],
146  index_type='y',
147  only_shift_first=only_shift_first)
148  shift_z_indexes_of_lines_in_ax(bk_animation,
149  shift_amount_per_frame,
150  ax_number=2,
151  n_line_number=1,
152  index_type='y',
153  only_shift_first=only_shift_first)
154 
155  bk_animation.change_y(1, 0)
156  bk_animation.change_x(3, 0, get_axis="y")
157  if(show_pad):
158  bk_animation.change_x(3, 1)
159  bk_animation.update_upper_springs(3, index_first_spring=index_first_spring)
160 
161  bk_animation.update_subplots()
162  sleep(bk_animation.sleep_amount)
163 
164  if(live_plotting):
165  init_plot_frames()
166  for i in range(0, frames):
167  plot_frames(i)
168  else:
169  ani = animation.FuncAnimation(bk_animation.fig,
170  plot_frames,
171  init_func=init_plot_frames,
172  frames=frames,
173  interval=30)
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',
177  writer=writer,
178  dpi=100)
179 
180 
181 def run_demo(
182  demo_number
183 ):
184  flags = {"no_pad": "--nopad"}
185  live_plotting = False
186  sample_mode = 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.",
192  "\n"
193  "This data for this run starts at a velocity og 1.49 and down",
194  "\n",
195  "to 0.0. Only a sample is plotted.",
196  "\n",
197  "The run will start in approximately 10 seconds.")
198  sleep(8)
199  pos_pos_spr_friction(run_name, shown_indexes)
200 
201 
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]))
207  else:
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))
211 ```
212 
213 ### Documentation of classes
214 
215 There are threes classes that are involved when making a live or movie plot. They are
216 
217 1. BKAnimation
218 2. SinglePlot
219 3. SingleLine
220 
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.
222 
223 ### BKAnimation
224 
225 * single_plots,
226 * frame_interval = 10,
227 * movement_per_frame = 10,
228 * n_frames = 10,
229 * fps = 10,
230 * sleep_amount = 1
231 
232 The values set are defaults that are overrided when set.
233 
234 key functions:
235 
236 * __init__
237  * Constructur, possible to set above variables when initiating
238  * ```bk_animation = BKAnimation([single_plot, single_plot_2])```
239 * init_live_plot
240  * initialize figure and setup specified figures
241  * ```bk_animation.init_live_plot((211, 212), (20,20))```
242 * init_subplots
243  * sets up each of the subplots
244 * init_specified_subplot
245  * sets up each line in a subplot
246 * update_subplots
247  * call after updating values in a plot
248 * update_specified_plots
249  * update each og the lines in a subplot
250 * update_live_*
251  * updates specific values in a line
252 
253 
254 ### SinglePlot
255 
256 Contains:
257 
258 * ax_number,
259 * x_lim = None,
260 * y_lim = None,
261 * single_line_list = []
262 * line_type = 'line
263 
264 key functions:
265 
266 * __init__
267  * constructor
268  * ```single_plot = SinglePlot(ax_number = 0)```
269  * ```single_plot = SinglePlot(ax_number = 1,single_line_list = [single_line])```
270 * append_single_line
271  * append a SingleLine object ot the SinglePlot
272 * change_*\_lim
273  * change limits of *
274 
275 
276 ### SingleLine
277 
278 Contains:
279 
280 * x_values
281 * y_values
282 * x_indexes
283 * y_indexes
284 * ax_number
285 * line_number
286 
287 key functions:
288 
289 * __init__
290  * constructor
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
293 * print_all
294  * prints current variable values