{ "cells": [ { "cell_type": "markdown", "id": "6f979a39", "metadata": {}, "source": [ "# Interactive Mandelbrot Set\n", "\n", "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. \n", "\n", "\n", "There are many other known fractals ." ] }, { "cell_type": "code", "execution_count": 3, "id": "b96de77a", "metadata": {}, "outputs": [], "source": [ "from numpy import * # because arrays are defined in numpy\n", "from numba import njit # This is the new line with numba\n", "from numba import prange\n", "\n", "@njit # this is an alias for @jit(nopython=True)\n", "def Mand(z0, max_steps):\n", " z = 0j # no need to specify type. \n", " # To initialize to complex number, just assign 0j==i*0\n", " for itr in range(max_steps):\n", " if abs(z)>2:\n", " return itr\n", " z = z*z + z0\n", " return max_steps\n", "\n", "@njit(parallel=True)\n", "def Mandelbrot3(data, ext, max_steps):\n", " \"\"\"\n", " ext[4] -- array of 4 values [min_x,max_x,min_y,max_y]\n", " Nxy -- int number of points in x and y direction\n", " max_steps -- how many steps we will try at most before we conclude the point is in the set\n", " \"\"\"\n", " Nx,Ny = shape(data) # 2D array should be already allocated we get its size\n", " for i in range(Nx):\n", " for j in prange(Ny): # note that we used prange instead of range.\n", " # this switches off parallelization of this loop, so that\n", " # only the outside loop over i is parallelized.\n", " x = ext[0] + (ext[1]-ext[0])*i/(Nx-1.)\n", " y = ext[2] + (ext[3]-ext[2])*j/(Ny-1.)\n", " # creating complex number of the fly\n", " data[i,j] = Mand(x + y*1j, max_steps) \n", "# data now contains integers. \n", "# MandelbrotSet has value 1000, and points not in the set have value <1000." ] }, { "cell_type": "code", "execution_count": 5, "id": "b50cb479", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Using matplotlib backend: MacOSX\n" ] } ], "source": [ "%matplotlib\n", "import matplotlib.pyplot as plt\n", "import matplotlib.cm as cm\n", "#from pylab import * # plotting library\n", "# don't use \"%matplotlib inline\"\n", "\n", "def ax_update(ax): # actual plotting routine\n", " ax.set_autoscale_on(False) # Otherwise, infinite loop\n", " # Get the range for the new area\n", " xstart, ystart, xdelta, ydelta = ax.viewLim.bounds\n", " xend = xstart + xdelta\n", " yend = ystart + ydelta\n", " ext=array([xstart,xend,ystart,yend])\n", " Mandelbrot3(data, ext, 1000) # actually producing new fractal\n", " \n", " # Update the image object with our new data and extent\n", " im = ax.images[-1] # take the latest object\n", " im.set_data(-log(data.T)) # update it with new data\n", " im.set_extent(ext) # change the extent\n", " ax.figure.canvas.draw_idle() # finally redraw\n", "\n", "\n", "data = zeros((1000,1000))\n", "ext=[-2,1,-1,1]\n", "Mandelbrot3(data, array(ext), 1000)\n", "fig,ax = plt.subplots(1,1)\n", "ax.imshow(-log(data.T), extent=ext, aspect='equal',origin='lower',cmap=cm.hot)\n", " \n", "ax.callbacks.connect('xlim_changed', ax_update)\n", "ax.callbacks.connect('ylim_changed', ax_update)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "id": "22f92109", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.18" } }, "nbformat": 4, "nbformat_minor": 5 }