Interactive zooming on Mandelbrot

Simple quib-based app for viewing and zooming on the Mandelbrot set.

  • Features

    • Calling a user-defined function

    • Quib-linked widgets

    • Inverse assignments

  • Try me

    • Try moving the region-of-interests in panels 1 and 2 to choose zoom-in areas.

from pyquibbler import iquib, initialize_quibbler, q
initialize_quibbler()
import matplotlib.pyplot as plt
from matplotlib.widgets import RectangleSelector, Slider
import numpy as np

%matplotlib tk
def mandelbrot(extent, num_pixels=200, num_iterations=30):
    '''
    calculate mandelbrot set in the extent range
    extent = [xmin, xmax, ymin, ymax]
    '''

    x_range = extent[0:2]
    y_range = extent[2:4]

    dx = np.diff(x_range)
    dy = np.diff(y_range)
    d = np.maximum(dx,dy) / num_pixels
    xy = np.mgrid[y_range[0]:y_range[1]:d, x_range[0]:x_range[1]:d]
    y, x = xy
    c = x + 1j * y
    z = np.zeros(np.shape(x))
    m = np.zeros(np.shape(x))

    import warnings
    warnings.filterwarnings("ignore")
    for i_iter in range(num_iterations):
        z = z*z + c
        m[(np.abs(z) > 2) & (m == 0)] = num_iterations - i_iter
    warnings.filterwarnings("default")
    m = np.flipud(m)

    return m
# Define input quibs:

# image resolution:
resolution = iquib(200)

# number of iterations for calculating convergence of the
# Mandelbrot set:
depth = iquib(200)

# selection areas for each of the panels:
XYs = []
XYs.append(iquib(np.array([-2.   ,  1.  , -1.5, 1.5  ])))
XYs.append(iquib(np.array([-1.55 , -0.55, -0.5, 0.39 ])))
XYs.append(iquib(np.array([-1.42 , -1.23, -0.1, 0.08 ])))

# Figure setup:
fig = plt.figure(figsize=(4.5,8))

for k in range(3):
    # Define a functional quib that calculates Mandelbrot:
    img = q(mandelbrot,XYs[k], resolution, depth)

    # Plot the image:
    axs = fig.add_axes([0.1, 0.13 + (2-k) * 0.28, 0.8, 0.26])
    axs.imshow(img, extent=XYs[k])
    axs.set_xticks([])
    axs.set_yticks([])
    axs.text(0.03,0.97,str(k), transform = axs.transAxes,
             fontsize=16, va='top',ha='left')

    # ROI selector:
    if k<2:
        RectangleSelector(axs, extents=XYs[k+1],
            props=dict(edgecolor='black', alpha=0.7, fill=False, linewidth=3))

# plot the depth slider
axs = fig.add_axes([0.35,0.08,0.4,0.03])
Slider(ax=axs, label='depth', valmin=0, valmax=200, valstep=1,
       valinit=depth);

# plot the resolution slider
axs = fig.add_axes([0.35,0.03,0.4,0.03])
Slider(ax=axs, label='resolution', valmin=10, valmax=300, valstep=10,
       valinit=resolution);
../_images/quibdemo_Mandelbrot.gif