14
14
You can copy and paste individual parts, or download the entire example
15
15
using the link at the bottom of the page.
16
16
"""
17
- import matplotlib .pyplot as plt
18
- import numpy as np
19
-
20
- from matplotlib .patches import Rectangle
21
17
18
+ import functools
22
19
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 ()
20
+ import matplotlib .pyplot as plt
21
+ from matplotlib .patches import Rectangle
22
+ import numpy as np
30
23
31
24
32
25
# A class that will regenerate a fractal set as we zoom in, so that you
@@ -40,9 +33,9 @@ def __init__(self, h=500, w=500, niter=50, radius=2., power=2):
40
33
self .radius = radius
41
34
self .power = power
42
35
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 )
36
+ def compute_image (self , xlim , ylim ):
37
+ self .x = np .linspace (* xlim , self .width )
38
+ self .y = np .linspace (* ylim , self .height ).reshape (- 1 , 1 )
46
39
c = self .x + 1.0j * self .y
47
40
threshold_time = np .zeros ((self .height , self .width ))
48
41
z = np .zeros (threshold_time .shape , dtype = complex )
@@ -56,38 +49,43 @@ def compute_image(self, xstart, xend, ystart, yend):
56
49
def ax_update (self , ax ):
57
50
ax .set_autoscale_on (False ) # Otherwise, infinite loop
58
51
# 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
52
+ self .width , self .height = ax .patch .get_window_extent ().size .round ().astype (int )
64
53
# 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 )
54
+ ax .images [- 1 ].set (data = self .compute_image (ax .get_xlim (), ax .get_ylim ()),
55
+ extent = (* ax .get_xlim (), * ax .get_ylim ()))
68
56
ax .figure .canvas .draw_idle ()
69
57
70
58
71
59
md = 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" )
60
+
61
+ fig1 , (ax_full , ax_zoom ) = plt .subplots (1 , 2 )
62
+ ax_zoom .imshow ([[0 ]], origin = "lower" ) # Empty initial image.
63
+ ax_zoom .set_title ("Zoom here" )
64
+
65
+ rect = Rectangle (
66
+ [0 , 0 ], 0 , 0 , facecolor = "none" , edgecolor = "black" , linewidth = 1.0 )
67
+ ax_full .add_patch (rect )
68
+
69
+
70
+ def update_rect (rect , ax ): # Let the rectangle track the bounds of the zoom axes.
71
+ xlo , xhi = ax .get_xlim ()
72
+ ylo , yhi = ax .get_ylim ()
73
+ rect .set_bounds ((xlo , ylo , xhi - xlo , yhi - ylo ))
74
+ ax .figure .canvas .draw_idle ()
75
+
76
+
77
+ # Connect for changing the view limits.
78
+ ax_zoom .callbacks .connect ("xlim_changed" , functools .partial (update_rect , rect ))
79
+ ax_zoom .callbacks .connect ("ylim_changed" , functools .partial (update_rect , rect ))
80
+
81
+ ax_zoom .callbacks .connect ("xlim_changed" , md .ax_update )
82
+ ax_zoom .callbacks .connect ("ylim_changed" , md .ax_update )
83
+
84
+ # Initialize: trigger image computation by setting view limits; set colormap limits;
85
+ # copy image to full view.
86
+ ax_zoom .set (xlim = (- 2 , .5 ), ylim = (- 1.25 , 1.25 ))
87
+ im = ax_zoom .images [0 ]
88
+ ax_zoom .images [0 ].set (clim = (im .get_array ().min (), im .get_array ().max ()))
89
+ ax_full .imshow (im .get_array (), extent = im .get_extent (), origin = "lower" )
92
90
93
91
plt .show ()
0 commit comments