Coding Example: The Mandelbrot Set (Python approach)
In this lesson, we are going to look at the Python implementation of the Mandelbrot set case study.
We'll cover the following...
We'll cover the following...
Python Implementation
A pure python implementation is written as:
Press + to interact
main.py
tools.py
# -----------------------------------------------------------------------------# From Numpy to Python# Copyright (2017) Nicolas P. Rougier - BSD license# More information at https://github.com/rougier/numpy-book# -----------------------------------------------------------------------------import numpy as npdef mandelbrot_python(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon=2.0):def mandelbrot(z, maxiter):c = zfor n in range(maxiter):if abs(z) > horizon:return nz = z*z + creturn maxiterr1 = [xmin+i*(xmax-xmin)/xn for i in range(xn)]r2 = [ymin+i*(ymax-ymin)/yn for i in range(yn)]return [mandelbrot(complex(r, i),maxiter) for r in r1 for i in r2]def mandelbrot(xmin, xmax, ymin, ymax, xn, yn, itermax, horizon=2.0):# Adapted from# https://thesamovar.wordpress.com/2009/03/22/fast-fractals-with-python-and-numpy/Xi, Yi = np.mgrid[0:xn, 0:yn]Xi, Yi = Xi.astype(np.uint32), Yi.astype(np.uint32)X = np.linspace(xmin, xmax, xn, dtype=np.float32)[Xi]Y = np.linspace(ymin, ymax, yn, dtype=np.float32)[Yi]C = X + Y*1jN_ = np.zeros(C.shape, dtype=np.uint32)Z_ = np.zeros(C.shape, dtype=np.complex64)Xi.shape = Yi.shape = C.shape = xn*ynZ = np.zeros(C.shape, np.complex64)for i in range(itermax):if not len(Z): break# Compute for relevant points onlynp.multiply(Z, Z, Z)np.add(Z, C, Z)# Failed convergenceI = abs(Z) > horizonN_[Xi[I], Yi[I]] = i+1Z_[Xi[I], Yi[I]] = Z[I]# Keep going with those who have not diverged yetnp.logical_not(I,I)Z = Z[I]Xi, Yi = Xi[I], Yi[I]C = C[I]return Z_.T, N_.Tif __name__ == '__main__':from matplotlib import colorsimport matplotlib.pyplot as pltfrom tools import timeit# Benchmarkxmin, xmax, xn = -2.25, +0.75, int(3000/3)ymin, ymax, yn = -1.25, +1.25, int(2500/3)maxiter = 200timeit("mandelbrot_python(xmin, xmax, ymin, ymax, xn, yn, maxiter)", globals())# Visualizationxmin, xmax, xn = -2.25, +0.75, int(3000/2)ymin, ymax, yn = -1.25, +1.25, int(2500/2)maxiter = 20horizon = 2.0 ** 40log_horizon = np.log(np.log(horizon))/np.log(2)Z, N = mandelbrot(xmin, xmax, ymin, ymax, xn, yn, maxiter, horizon)# Normalized recount as explained in:# http://linas.org/art-gallery/escape/smooth.htmlM = np.nan_to_num(N + 1 - np.log(np.log(abs(Z)))/np.log(2) + log_horizon)dpi = 72width = 10height = 10*yn/xnfig = plt.figure(figsize=(width, height), dpi=dpi)ax = fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False, aspect=1)light = colors.LightSource(azdeg=315, altdeg=10)plt.imshow(light.shade(M, cmap=plt.cm.hot, vert_exag=1.5,norm = colors.PowerNorm(0.3), blend_mode='hsv'),extent=[xmin, xmax, ymin, ymax], interpolation="bicubic")ax.set_xticks([])ax.set_yticks([])plt.savefig("output/mandelbrot.png")plt.show()
Output
The output of the above code would look like this:
The interesting (and slow) part of this code is the mandelbrot function that actually computes the sequence ...