-
-
Save ChrisBeaumont/4090682 to your computer and use it in GitHub Desktop.
"""From the numba examples | |
(https://github.com/numba/numba/blob/master/examples/mandel.py), | |
but tweaked to recalculate on the fly as the viewport changes""" | |
from numba import autojit | |
import numpy as np | |
from pylab import imshow, jet, show, ion | |
import matplotlib.pyplot as plt | |
from matplotlib import rcParams | |
rcParams['image.origin'] = 'lower' | |
@autojit | |
def mandel(x, y, max_iters): | |
""" | |
Given the real and imaginary parts of a complex number, | |
determine if it is a candidate for membership in the Mandelbrot | |
set given a fixed number of iterations. | |
""" | |
i = 0 | |
c = complex(x,y) | |
z = 0.0j | |
for i in range(max_iters): | |
z = z*z + c | |
if (z.real*z.real + z.imag*z.imag) >= 4: | |
return i | |
return 255 | |
@autojit | |
def create_fractal(min_x, max_x, min_y, max_y, image, iters): | |
height = image.shape[0] | |
width = image.shape[1] | |
pixel_size_x = (max_x - min_x) / width | |
pixel_size_y = (max_y - min_y) / height | |
for x in range(width): | |
real = min_x + x * pixel_size_x | |
for y in range(height): | |
imag = min_y + y * pixel_size_y | |
color = mandel(real, imag, iters) | |
image[y, x] = color | |
return image | |
def update_axes(ax): | |
xlim = ax.get_xlim() | |
ylim = ax.get_ylim() | |
trans = ax.transAxes | |
ext = trans.transform([[1, 1]]) - trans.transform([[0, 0]]) | |
nx = ext[0, 0] | |
ny = ext[0, 1] | |
image = np.zeros((ny, nx), dtype=np.uint8) | |
create_fractal(xlim[0], xlim[1], ylim[0], ylim[1], image, 255) | |
ax.clear() | |
ax.imshow(image, extent=[xlim[0], xlim[1], ylim[0], ylim[1]], zorder=0) | |
ax.figure.canvas.draw() | |
image = np.zeros((500, 750), dtype=np.uint8) | |
artist = plt.imshow(create_fractal(-2.0, 1.0, -1.0, 1.0, image, 255), | |
extent=[-2.0, 1.0, -1.0, 1.0]) | |
ax = plt.gca() | |
ax.figure.canvas.mpl_connect('button_release_event', lambda x: update_axes(ax)) | |
ax.set_title('Zoom in') | |
plt.show() |
I think you should replace xranges with np.arange and the for loops with Numpy functions as they are much faster.
The loops in create_fractal can be wrapped in a utility function and then use np.apply_over_axes.
@peterhil take a look at the Numba project, where autojit comes from. It compiles python functions into LLVM, so the loops run at ~C speed. The code runs about 1000x faster after applying the autojit decorator. This code is lifted from the numba repo, with the update_axes function added for fun times.
Somehow I get mirrored zooming in this, unless I swap the ylim parameters in line 51, create_fractal(xlim[0], xlim[1], ylim[1], ylim[0], image, 255)
@petrushy You probably have 'image.origin = upper' somewhere in your matplotlibrc file (or maybe that's the default, and it's overridden to lower in mine). Anyways, I think the new version should resolve that problem.
Nice! What does autojit do?