def simple:
import pandas as pd
import matplotlib.pyplot as plt
import pandas_alive
import numpy as np
# Physical constants
g = 9.81
L = .4
mu = 0.2
THETA_0 = np.pi * 70 / 180 # init angle = 70degs
THETA_DOT_0 = 0 # no init angVel
DELTA_T = 0.01 # time stepping
T = 1.5 # time period
# Definition of ODE (ordinary differential equation)
def get_theta_double_dot(theta, theta_dot):
return -mu * theta_dot - (g / L) * np.sin(theta)
# Solution to the differential equation
def pendulum(t):
# initialise changing values
theta = THETA_0
theta_dot = THETA_DOT_0
delta_t = DELTA_T
ang =
ang_vel =
ang_acc =
times =
for time in np.arange(0, t, delta_t):
theta_double_dot = get_theta_double_dot(
theta, theta_dot
)
theta += theta_dot * delta_t
theta_dot += theta_double_dot * delta_t
times.append(time)
ang.append(theta)
ang_vel.append(theta_dot)
ang_acc.append(theta_double_dot)
data = np.array([ang, ang_vel, ang_acc])
return pd.DataFrame(data=data.T, index=np.array(times), columns=['angle', 'ang_vel', 'ang_acc'])
# units used for ref: ['angle [rad]', 'ang_vel [rad/s]', 'ang_acc [rad/s^2]']
df = pendulum(T)
df.index.names = ['Time (s)']
print(df)
# generate dataFrame for animated bubble plot
df2 = pd.DataFrame(index=df.index)
df2['dx (m)'] = L * np.sin(df['angle'])
df2['dy (m)'] = -L * np.cos(df['angle'])
df2['ang_vel'] = abs(df['ang_vel'])
df2['size'] = df2['ang_vel'] * 100 # scale angular vels to get nice size on bubble plot
print(df2)
# static pandas plots
#
# print(plt.style.available)
# NOTE: 2 lines below required in Jupyter to switch styles correctly
plt.rcParams.update(plt.rcParamsDefault)
plt.style.use('ggplot') # set plot style
fig, (ax1a, ax2b) = plt.subplots(1, 2, figsize=(8, 4), dpi=100) # 1 row, 2 subplots
# fig.subplots_adjust(wspace=0.1) # space subplots in row
fig.set_tight_layout(True)
fontsize = 'small'
df.plot(ax=ax1a).legend(fontsize=fontsize)
ax1a.set_title('Outputs vs Time', fontsize='medium')
ax1a.set_xlabel('Time [s]', fontsize=fontsize)
ax1a.set_ylabel('Amplitudes', fontsize=fontsize);
df.plot(ax=ax2b, x='angle', y=['ang_vel', 'ang_acc']).legend(fontsize=fontsize)
ax2b.set_title('Outputs vs Angle | Phase-Space', fontsize='medium')
ax2b.set_xlabel('Angle [rad]', fontsize=fontsize)
ax2b.set_ylabel('Angular Velocity / Acc', fontsize=fontsize)
# sample scatter plot with colorbar
fig, ax = plt.subplots
sc = ax.scatter(df2['dx (m)'], df2['dy (m)'], s=df2['size'] * .1, c=df2['ang_vel'], cmap='jet')
cbar = fig.colorbar(sc)
cbar.set_label(label='ang_vel [rad/s]', fontsize='small')
# sc.set_clim(350, 400)
ax.tick_params(labelrotation=0, labelsize='medium')
ax_scale = 1.
ax.set_xlim(-L * ax_scale, L * ax_scale)
ax.set_ylim(-L * ax_scale - 0.1, L * ax_scale - 0.1)
# make axes square: a circle shows as a circle
ax.set_aspect(1 / ax.get_data_ratio)
ax.arrow(0, 0, df2['dx (m)'].iloc[-1], df2['dy (m)'].iloc[-1],
color='dimgray', ls=':', lw=2.5, width=.0, head_width=0, zorder=-1
)
ax.text(0, 0.15, s='size and colour of pendulum bob\nbased on pd column\nfor angular velocity',
ha='center', va='center')
# plt.show
dpi = 100
ax_scale = 1.1
figsize = (3, 3)
fontsize = 'small'
# set up figure to pass onto `pandas_alive`
# NOTE: by using Figure (capital F) instead of figure `FuncAnimation` seems to run twice as fast!
# fig1, ax1 = plt.subplots
fig1 = plt.Figure
ax1 = fig1.add_subplot
fig1.set_size_inches(figsize)
ax1.set_title('Simple pendulum animation, L=' + str(L) + 'm', fontsize='medium')
ax1.set_xlabel('Time (s)', color='dimgray', fontsize=fontsize)
ax1.set_ylabel('Amplitudes', color='dimgray', fontsize=fontsize)
ax1.tick_params(labelsize=fontsize)
# pandas_alive
line_chart = df.plot_animated(filename='pend-line.gif', kind='line', period_label={'x': 0.05, 'y': 0.9},
steps_per_period=1, interpolate_period=False, period_length=50,
period_fmt='Time:{x:10.2f}',
enable_progress_bar=True, fixed_max=True, dpi=100, fig=fig1
)
plt.close
# Video('examples/pend-line.mp4', html_attributes='controls muted autoplay')
# set up and generate animated scatter plot
#
# set up figure to pass onto `pandas_alive`
# NOTE: by using Figure (capital F) instead of figure `FuncAnimation` seems to run twice as fast!
fig1sc = plt.Figure
ax1sc = fig1sc.add_subplot
fig1sc.set_size_inches(figsize)
ax1sc.set_title('Simple pendulum animation, L=' + str(L) + 'm', fontsize='medium')
ax1sc.set_xlabel('Time (s)', color='dimgray', fontsize=fontsize)
ax1sc.set_ylabel('Amplitudes', color='dimgray', fontsize=fontsize)
ax1sc.tick_params(labelsize=fontsize)
# pandas_alive
scatter_chart = df.plot_animated(filename='pend-scatter.gif', kind='scatter', period_label={'x': 0.05, 'y': 0.9},
steps_per_period=1, interpolate_period=False, period_length=50,
period_fmt='Time:{x:10.2f}',
enable_progress_bar=True, fixed_max=True, dpi=100, fig=fig1sc, size='ang_vel'
)
plt.close
print('Points size follows one of the pd columns: ang_vel')
# Video('./pend-scatter.gif', html_attributes='controls muted autoplay')
# set up and generate animated bar race chart
#
# set up figure to pass onto `pandas_alive`
# NOTE: by using Figure (capital F) instead of figure `FuncAnimation` seems to run twice as fast!
fig2 = plt.Figure
ax2 = fig2.add_subplot
fig2.set_size_inches(figsize)
ax2.set_title('Simple pendulum animation, L=' + str(L) + 'm', fontsize='medium')
ax2.set_xlabel('Amplitudes', color='dimgray', fontsize=fontsize)
ax2.set_ylabel('', color='dimgray', fontsize='x-small')
ax2.tick_params(labelsize=fontsize)
# pandas_alive
race_chart = df.plot_animated(filename='pend-race.gif', kind='race', period_label={'x': 0.05, 'y': 0.9},
steps_per_period=1, interpolate_period=False, period_length=50,
period_fmt='Time:{x:10.2f}',
enable_progress_bar=True, fixed_max=False, dpi=100, fig=fig2
)
plt.close
# set up and generate bubble animated plot
#
# set up figure to pass onto `pandas_alive`
# NOTE: by using Figure (capital F) instead of figure `FuncAnimation` seems to run twice as fast!
fig3 = plt.Figure
ax3 = fig3.add_subplot
fig3.set_size_inches(figsize)
ax3.set_title('Simple pendulum animation, L=' + str(L) + 'm', fontsize='medium')
ax3.set_xlabel('Hor Displacement (m)', color='dimgray', fontsize=fontsize)
ax3.set_ylabel('Ver Displacement (m)', color='dimgray', fontsize=fontsize)
# limits & ratio below get the graph square
ax3.set_xlim(-L * ax_scale, L * ax_scale)
ax3.set_ylim(-L * ax_scale - 0.1, L * ax_scale - 0.1)
ratio = 1. # this is visual ratio of axes
ax3.set_aspect(ratio / ax3.get_data_ratio)
ax3.arrow(0, 0, df2['dx (m)'].iloc[-1], df2['dy (m)'].iloc[-1],
color='dimgray', ls=':', lw=1, width=.0, head_width=0, zorder=-1)
# pandas_alive
bubble_chart = df2.plot_animated(
kind='bubble', filename='pend-bubble.gif',
x_data_label='dx (m)', y_data_label='dy (m)',
size_data_label='size', color_data_label='ang_vel', cmap='jet',
period_label={'x': 0.05, 'y': 0.9}, vmin=None, vmax=None,
steps_per_period=1, interpolate_period=False, period_length=50, period_fmt='Time:{x:10.2f}s',
enable_progress_bar=True, fixed_max=False, dpi=dpi, fig=fig3
)
plt.close
print('Bubble size & colour animates with pd data column for ang_vel.')
# Combined plots
#
fontsize = 'x-small'
# Otherwise titles overlap and subplots_adjust does nothing
from matplotlib import rcParams
rcParams.update({'figure.autolayout': False})
figs = plt.Figure(figsize=(9, 4), dpi=100)
figs.subplots_adjust(wspace=0.1)
gs = figs.add_gridspec(2, 2)
ax1 = figs.add_subplot(gs[0, 0])
ax1.set_xlabel('Time(s)', color='dimgray', fontsize=fontsize)
ax1.set_ylabel('Amplitudes', color='dimgray', fontsize=fontsize)
ax1.tick_params(labelsize=fontsize)
ax2 = figs.add_subplot(gs[1, 0])
ax2.set_xlabel('Amplitudes', color='dimgray', fontsize=fontsize)
ax2.set_ylabel('', color='dimgray', fontsize=fontsize)
ax2.tick_params(labelsize=fontsize)
ax3 = figs.add_subplot(gs[:, 1])
ax3.set_xlabel('Hor Displacement (m)', color='dimgray', fontsize=fontsize)
ax3.set_ylabel('Ver Displacement (m)', color='dimgray', fontsize=fontsize)
ax3.tick_params(labelsize=fontsize)
# limits & ratio below get the graph square
ax3.set_xlim(-L * ax_scale, L * ax_scale)
ax3.set_ylim(-L * ax_scale - 0.1, L * ax_scale - 0.1)
ratio = 1. # this is visual ratio of axes
ax3.set_aspect(ratio / ax3.get_data_ratio)
line_chart.ax = ax1
race_chart.ax = ax2
bubble_chart.ax = ax3
plots = [line_chart, race_chart, bubble_chart]
# pandas_alive combined using custom figure
pandas_alive.animate_multiple_plots(
filename='pend-combined.gif', plots=plots, custom_fig=figs, dpi=100, enable_progress_bar=True,
adjust_subplot_left=0.2, adjust_subplot_right=None,
title='Simple pendulum animations, L=' + str(L) + 'm', title_fontsize='medium'
)
plt.close