#!/usr/bin/env python # coding: utf-8 # # Interactive Mandelbrot Set # # Mandelbrot Set is a fractal, which is self-similar. If you zoom in on a fractal object it will look similar, (possibly rotated), or exactly like the original shape. # # # There are many other known fractals . # In[3]: from numpy import * # because arrays are defined in numpy from numba import njit # This is the new line with numba from numba import prange @njit # this is an alias for @jit(nopython=True) def Mand(z0, max_steps): z = 0j # no need to specify type. # To initialize to complex number, just assign 0j==i*0 for itr in range(max_steps): if abs(z)>2: return itr z = z*z + z0 return max_steps @njit(parallel=True) def Mandelbrot3(data, ext, max_steps): """ ext[4] -- array of 4 values [min_x,max_x,min_y,max_y] Nxy -- int number of points in x and y direction max_steps -- how many steps we will try at most before we conclude the point is in the set """ Nx,Ny = shape(data) # 2D array should be already allocated we get its size for i in range(Nx): for j in prange(Ny): # note that we used prange instead of range. # this switches off parallelization of this loop, so that # only the outside loop over i is parallelized. x = ext[0] + (ext[1]-ext[0])*i/(Nx-1.) y = ext[2] + (ext[3]-ext[2])*j/(Ny-1.) # creating complex number of the fly data[i,j] = Mand(x + y*1j, max_steps) # data now contains integers. # MandelbrotSet has value 1000, and points not in the set have value <1000. # In[5]: get_ipython().run_line_magic('matplotlib', '') import matplotlib.pyplot as plt import matplotlib.cm as cm #from pylab import * # plotting library # don't use "%matplotlib inline" def ax_update(ax): # actual plotting routine ax.set_autoscale_on(False) # Otherwise, infinite loop # Get the range for the new area xstart, ystart, xdelta, ydelta = ax.viewLim.bounds xend = xstart + xdelta yend = ystart + ydelta ext=array([xstart,xend,ystart,yend]) Mandelbrot3(data, ext, 1000) # actually producing new fractal # Update the image object with our new data and extent im = ax.images[-1] # take the latest object im.set_data(-log(data.T)) # update it with new data im.set_extent(ext) # change the extent ax.figure.canvas.draw_idle() # finally redraw data = zeros((1000,1000)) ext=[-2,1,-1,1] Mandelbrot3(data, array(ext), 1000) fig,ax = plt.subplots(1,1) ax.imshow(-log(data.T), extent=ext, aspect='equal',origin='lower',cmap=cm.hot) ax.callbacks.connect('xlim_changed', ax_update) ax.callbacks.connect('ylim_changed', ax_update) plt.show() # In[ ]: