Barnsley-Fern leaf fractal pattern¶

See the Wikipedia page for reference.

Libraries¶

In [1]:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from matplotlib.animation import FuncAnimation
plt.rcParams["animation.html"] = "jshtml"

Variables¶

  • transition matrices and their probabilities: they define the shape of the 'leaf';
  • number of iterations $N$;
  • starting point $x$.
In [2]:
matrices = [
np.matrix([
    [0.00, 0.00, 0.00],
    [0.00, 0.16, 0.00]
]),
np.matrix([
    [0.85, 0.04, 0.00],
    [-0.04, 0.85, 1.60]
]),
np.matrix([
    [0.20, -0.26, 0.00],
    [0.23, 0.22, 1.60]
]),
np.matrix([
    [-0.15, 0.28, 0.00],
    [0.26, 0.24, 0.44]
])
]

probabilities = [0.01, 0.85, 0.07, 0.07]

x = np.matrix([[0.00],
               [0.00]]) # note: it is a column vector

N = 10000 #number of iterations

Main algorithm¶

In [3]:
#cumulative probabilities
cumulatives = [sum(probabilities[:i+1]) for i in range(len(probabilities))]
#time series of points
points = np.empty((N,2))
points[0] = x.T # note: save it as a row vector

for n in range(1, N):
    # extract a random matrix and apply it to [x,1]
    r = np.random.random()
    for c,mat in zip(cumulatives, matrices):
        if r < c:
            x = mat @ np.concatenate([x,[[1]]])
            break
    points[n] = x.T

Rendering

In [4]:
fig,ax = plt.subplots(figsize=(8,8))
ax.axis('equal')
ax.axis([-5.5,5.5, -0.5,10.5])
## simple plot
#ax.scatter(points[:,0],points[:,1], s=1, c='g', marker='.')
#plt.show()

## animation
l, = ax.plot([],[],'g.', markersize=1)
every = 50
def animate(i):
    l.set_data(points[:i*every,0], points[:i*every,1])

ani = FuncAnimation(fig, animate, frames=N//every)
ani
Out[4]:
In [ ]: