149 lines
3.7 KiB
Python

from functools import partial
import numpy as np
import sympy
import matplotlib.pyplot as plt
from sympy.plotting import plot_implicit
from matplotlib import animation
from carry import Carry
def make_animation(fig, frames, **kwargs):
fig.tight_layout()
#why isn't this how the function is exposed by default
return lambda func: animation.FuncAnimation(fig, func, frames, init_func=lambda: None, **kwargs)
def poly_from_array(array):
ret = 0
for i, row in enumerate(array):
for j, val in enumerate(row):
ret += val*(x**i * y**j)
return ret
x, y = sympy.symbols("x y")
xy_2 = Carry([[2,-1],[-1,0]])
xy_3 = Carry([[3,-1],[-1,0]])
x2y_3 = Carry([[3,-2],[-1,0]])
x3y_4 = Carry([[4,-3],[-1,0]])
laplace = Carry([[0,-1,0],[-1,4,-1],[0,-1,0]])
laplace3 = Carry([[0,0,0],[-1,3,-1],[0,-1,0]])
almost_folium = Carry([[0,0,-1], [0,2,0], [-1,0,0]])
folium = Carry([[0,0,0,-1], [0,2,0,0], [0,0,0,0], [-1,0,0,0]])
folium3 = Carry([[0,0,0,-1], [0,3,0,0], [0,0,0,0], [-1,0,0,0]])
folium4 = Carry([ [ 0, 0,0,-1, 0],
[ 0, 0,0, 0,-1],
[ 0, 0,4, 0, 0],
[-1, 0,0, 0, 0],
[ 0,-1,0, 0, 0]])
def triangle_spread(n):
ret = np.zeros((n + 1, n + 1), dtype=np.int32)
ret[0, 0] = -1
ret[1, 1] = 3
ret[n, 0] = -1
ret[0, n] = -1
return ret
triangle1 = Carry(triangle_spread(1))
triangle2 = Carry(triangle_spread(2))
triangle3 = Carry(triangle_spread(3)) #factorable!
triangle4 = Carry(triangle_spread(4))
tri3_rot = Carry([ [ 0, 0,-1, 0, 0],
[ 0, 0, 3, 0, 0],
[-1, 0, 0, 0,-1] ])
tri3_rot_real = Carry([ [ 0, 0, 0,-1, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 3, 0, 0, 0],
[-1, 0, 0, 0, 0, 0,-1] ])
tri3_rot2 = Carry([ [ 0,-1, 0],
[ 0, 3, 0],
[-1, 0,-1] ])
tri3_tall = Carry([ [ 0,-1, 0],
[ 0, 0, 0],
[ 0, 3, 0],
[-1, 0,-1] ])
tri3_tall2 = Carry([ [ 0,-1, 0],
[ 0, 3, 0],
[ 0, 0, 0],
[-1, 0,-1] ])
def start_anim(dims=100, carry=xy_2, frames=None, interval=200, inter='add', i_val=1, center=(0,0)):
if center == (0,0) and carry.over_pos != center:
center = (dims // 2, dims // 2)
if inter == 'add':
next_func = partial(carry.add, val=i_val, center=center)
elif inter == 'mult':
if i_val == 1:
raise ValueError(f"too small value {i_val} for repeated multiplication")
next_func = partial(carry.mult, val=i_val, center=center)
else:
raise ValueError(f"Cannot use {repr(inter)} for animation")
zero = np.zeros((dims, dims))
zero[center] = 1
val = [1]
fig = plt.gcf()
plt.title('0')
image = plt.imshow(zero)
image.set_clim(0, carry.overflow-1)
@make_animation(fig, frames, interval=interval)
def ret(fr):
next_func(zero)
# if next_func != xy_2.add:
# fr = sum(i*(invalid**j) for i,j in zip(zero[0], range(dims))) - 1
if inter == 'add':
val[0] += i_val
else:
val[0] *= i_val
plt.title(f"{val[0]}")
image.set_data(zero)
fig.tight_layout()
return ret
def anim_curves(dims=25, invalid=2, frames=None, interval=200, next_func=xy_2.add):
zero = np.zeros((dims, dims), dtype=np.int32)
#zero[0,0] = 1
fig = plt.gcf()
#plt.colorbar()
#temp = plt.figure
#I hate doing it, but there's no other way to get the figure before it's plotted
plt.figure = bindfig(fig)
@make_animation(fig, frames, interval=interval)
def ret(fr):
next_func(zero, invalid)
fig.clf()
plot = plot_implicit(poly_from_array(zero) - fr, backend='matplotlib')
plt.title(f"{fr+1}")
print(fr)
return ret
writer = animation.writers['ffmpeg'](fps=15, metadata={'artist': 'Me'})
def bindfig(fig):
def ret(**kwargs):
for i, j in kwargs.items():
if i == "figsize":
if j is not None:
fig.set_figwidth(j[0])
fig.set_figheight(j[1])
continue
fig.__dict__["set_" + i](j)
return fig
return ret