1
# Creates two identical panels. Zooming in on the right panel will show
2
# a rectangle in the first panel, denoting the zoomed region.
4
import matplotlib.pyplot as plt
5
from matplotlib.patches import Rectangle
7
# We just subclass Rectangle so that it can be called with an Axes
8
# instance, causing the rectangle to update its shape to match the
10
class UpdatingRect(Rectangle):
11
def __call__(self, ax):
12
self.set_bounds(*ax.viewLim.bounds)
13
ax.figure.canvas.draw_idle()
15
# A class that will regenerate a fractal set as we zoom in, so that you
16
# can actually see the increasing detail. A box in the left panel will show
17
# the area to which we are zoomed.
18
class MandlebrotDisplay(object):
19
def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
26
def __call__(self, xstart, xend, ystart, yend):
27
self.x = np.linspace(xstart, xend, self.width)
28
self.y = np.linspace(ystart, yend, self.height).reshape(-1,1)
29
c = self.x + 1.0j * self.y
30
threshold_time = np.zeros((self.height, self.width))
31
z = np.zeros(threshold_time.shape, dtype=np.complex)
32
mask = np.ones(threshold_time.shape, dtype=np.bool)
33
for i in xrange(self.niter):
34
z[mask] = z[mask]**self.power + c[mask]
35
mask = (np.abs(z) < self.radius)
36
threshold_time += mask
39
def ax_update(self, ax):
40
ax.set_autoscale_on(False) # Otherwise, infinite loop
42
#Get the number of points from the number of pixels in the window
43
dims = ax.axesPatch.get_window_extent().bounds
44
self.width = int(dims[2] + 0.5)
45
self.height = int(dims[2] + 0.5)
47
#Get the range for the new area
48
xstart,ystart,xdelta,ydelta = ax.viewLim.bounds
49
xend = xstart + xdelta
50
yend = ystart + ydelta
52
# Update the image object with our new data and extent
54
im.set_data(self.__call__(xstart, xend, ystart, yend))
55
im.set_extent((xstart, xend, ystart, yend))
56
ax.figure.canvas.draw_idle()
58
md = MandlebrotDisplay()
59
Z = md(-2., 0.5, -1.25, 1.25)
62
ax1 = fig.add_subplot(1, 2, 1)
63
ax1.imshow(Z, origin='lower', extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))
65
ax2 = fig.add_subplot(1, 2, 2)
66
ax2.imshow(Z, origin='lower', extent=(md.x.min(), md.x.max(), md.y.min(), md.y.max()))
68
rect = UpdatingRect([0, 0], 0, 0, facecolor='None', edgecolor='black')
69
rect.set_bounds(*ax2.viewLim.bounds)
72
# Connect for changing the view limits
73
ax2.callbacks.connect('xlim_changed', rect)
74
ax2.callbacks.connect('ylim_changed', rect)
76
ax2.callbacks.connect('xlim_changed', md.ax_update)
77
ax2.callbacks.connect('ylim_changed', md.ax_update)