1414 You can copy and paste individual parts, or download the entire example
1515 using the link at the bottom of the page.
1616"""
17+
18+ import functools
19+
1720import matplotlib .pyplot as plt
1821import numpy as np
1922
2023from matplotlib .patches import Rectangle
2124
2225
23- # We just subclass Rectangle so that it can be called with an Axes
24- # instance, causing the rectangle to update its shape to match the
25- # bounds of the Axes
26- class UpdatingRect (Rectangle ):
27- def __call__ (self , ax ):
28- self .set_bounds (* ax .viewLim .bounds )
29- ax .figure .canvas .draw_idle ()
30-
31-
3226# A class that will regenerate a fractal set as we zoom in, so that you
3327# can actually see the increasing detail. A box in the left panel will show
3428# the area to which we are zoomed.
@@ -40,9 +34,9 @@ def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
4034 self .radius = radius
4135 self .power = power
4236
43- def compute_image (self , xstart , xend , ystart , yend ):
44- self .x = np .linspace (xstart , xend , self .width )
45- self .y = np .linspace (ystart , yend , self .height ).reshape (- 1 , 1 )
37+ def compute_image (self , xlim , ylim ):
38+ self .x = np .linspace (* xlim , self .width )
39+ self .y = np .linspace (* ylim , self .height ).reshape (- 1 , 1 )
4640 c = self .x + 1.0j * self .y
4741 threshold_time = np .zeros ((self .height , self .width ))
4842 z = np .zeros (threshold_time .shape , dtype = complex )
@@ -56,38 +50,43 @@ def compute_image(self, xstart, xend, ystart, yend):
5650 def ax_update (self , ax ):
5751 ax .set_autoscale_on (False ) # Otherwise, infinite loop
5852 # Get the number of points from the number of pixels in the window
59- self .width , self .height = \
60- np .round (ax .patch .get_window_extent ().size ).astype (int )
61- # Get the range for the new area
62- vl = ax .viewLim
63- extent = vl .x0 , vl .x1 , vl .y0 , vl .y1
53+ self .width , self .height = ax .patch .get_window_extent ().size .round ().astype (int )
6454 # Update the image object with our new data and extent
65- im = ax .images [- 1 ]
66- im .set_data (self .compute_image (* extent ))
67- im .set_extent (extent )
55+ ax .images [- 1 ].set (data = self .compute_image (ax .get_xlim (), ax .get_ylim ()),
56+ extent = (* ax .get_xlim (), * ax .get_ylim ()))
6857 ax .figure .canvas .draw_idle ()
6958
7059
7160md = MandelbrotDisplay ()
72- Z = md .compute_image (- 2. , 0.5 , - 1.25 , 1.25 )
73-
74- fig1 , (ax1 , ax2 ) = plt .subplots (1 , 2 )
75- ax1 .imshow (Z , origin = 'lower' ,
76- extent = (md .x .min (), md .x .max (), md .y .min (), md .y .max ()))
77- ax2 .imshow (Z , origin = 'lower' ,
78- extent = (md .x .min (), md .x .max (), md .y .min (), md .y .max ()))
79-
80- rect = UpdatingRect (
81- [0 , 0 ], 0 , 0 , facecolor = 'none' , edgecolor = 'black' , linewidth = 1.0 )
82- rect .set_bounds (* ax2 .viewLim .bounds )
83- ax1 .add_patch (rect )
84-
85- # Connect for changing the view limits
86- ax2 .callbacks .connect ('xlim_changed' , rect )
87- ax2 .callbacks .connect ('ylim_changed' , rect )
88-
89- ax2 .callbacks .connect ('xlim_changed' , md .ax_update )
90- ax2 .callbacks .connect ('ylim_changed' , md .ax_update )
91- ax2 .set_title ("Zoom here" )
61+
62+ fig1 , (ax_full , ax_zoom ) = plt .subplots (1 , 2 )
63+ ax_zoom .imshow ([[0 ]], origin = "lower" ) # Empty initial image.
64+ ax_zoom .set_title ("Zoom here" )
65+
66+ rect = Rectangle (
67+ [0 , 0 ], 0 , 0 , facecolor = "none" , edgecolor = "black" , linewidth = 1.0 )
68+ ax_full .add_patch (rect )
69+
70+
71+ def update_rect (rect , ax ): # Let the rectangle track the bounds of the zoom axes.
72+ xlo , xhi = ax .get_xlim ()
73+ ylo , yhi = ax .get_ylim ()
74+ rect .set_bounds ((xlo , ylo , xhi - xlo , yhi - ylo ))
75+ ax .figure .canvas .draw_idle ()
76+
77+
78+ # Connect for changing the view limits.
79+ ax_zoom .callbacks .connect ("xlim_changed" , functools .partial (update_rect , rect ))
80+ ax_zoom .callbacks .connect ("ylim_changed" , functools .partial (update_rect , rect ))
81+
82+ ax_zoom .callbacks .connect ("xlim_changed" , md .ax_update )
83+ ax_zoom .callbacks .connect ("ylim_changed" , md .ax_update )
84+
85+ # Initialize: trigger image computation by setting view limits; set colormap limits;
86+ # copy image to full view.
87+ ax_zoom .set (xlim = (- 2 , .5 ), ylim = (- 1.25 , 1.25 ))
88+ im = ax_zoom .images [0 ]
89+ ax_zoom .images [0 ].set (clim = (im .get_array ().min (), im .get_array ().max ()))
90+ ax_full .imshow (im .get_array (), extent = im .get_extent (), origin = "lower" )
9291
9392plt .show ()
0 commit comments