2323# the image namespace
2424from matplotlib ._image import * # noqa: F401, F403
2525from ._data_containers .description import Desc
26- from ._data_containers ._helpers import _get_graph
26+ from ._data_containers ._helpers import _get_graph , check_container
2727import matplotlib .artist as martist
2828import matplotlib .colorizer as mcolorizer
2929from matplotlib .backend_bases import FigureCanvasBase
@@ -347,21 +347,38 @@ def __init__(self, ax,
347347 np .array ([0. ,1. ]),
348348 np .array ([[]]),
349349 )
350+ self .__query = None
350351 self ._imcache = None
351352
352353 self ._internal_update (kwargs )
353354
355+ @property
356+ def _query (self ):
357+ if self .__query is not None :
358+ return self .__query
359+ return self ._container .query (_get_graph (self .axes ))[0 ]
360+
361+ def _cache_query (self ):
362+ self .__query = self ._container .query (_get_graph (self .axes ))[0 ]
363+
354364 @property
355365 def _image_array (self ):
356- return self ._container . query ( _get_graph ( self . axes ))[ 0 ] ["image" ]
366+ return self ._query ["image" ]
357367
358368 @property
359369 def _A (self ):
360370 return self ._image_array
361371
362372 @_A .setter
363373 def _A (self , val ):
364- return
374+ if val is None :
375+ # This case is needed for the transition because
376+ # ColorizingArtist sets `_A = None` during init
377+ return
378+ check_container (self , ImageContainer , "Setting _A" )
379+ self ._container .image = self ._normalize_image_array (val )
380+ self ._imcache = None
381+ self .stale = True
365382
366383 def set_container (self , container ):
367384 self ._container = container
@@ -379,7 +396,11 @@ def __str__(self):
379396
380397 def __getstate__ (self ):
381398 # Save some space on the pickle by not saving the cache.
382- return {** super ().__getstate__ (), "_imcache" : None }
399+ return {
400+ ** super ().__getstate__ (),
401+ "_imcache" : None ,
402+ "_ImageBase__query" : None ,
403+ }
383404
384405 def get_size (self ):
385406 """Return the size of the image as tuple (numrows, numcols)."""
@@ -689,6 +710,8 @@ def draw(self, renderer):
689710 if not self .get_visible ():
690711 self .stale = False
691712 return
713+ # Update the cached version of the query
714+ self ._cache_query ()
692715 # for empty images, there is nothing to draw!
693716 if self .get_array ().size == 0 :
694717 self .stale = False
@@ -781,11 +804,9 @@ def set_data(self, A):
781804 ----------
782805 A : array-like or `PIL.Image.Image`
783806 """
784- if not isinstance (self ._container , ImageContainer ):
785- raise TypeError ("Cannot use 'set_data' on custom container types" )
807+ check_container (self , ImageContainer , "'set_data'" )
786808 if isinstance (A , PIL .Image .Image ):
787809 A = pil_to_array (A ) # Needed e.g. to apply png palette.
788- # self._A = self._normalize_image_array(A)
789810 self ._container .image = self ._normalize_image_array (A )
790811 self ._imcache = None
791812 self .stale = True
@@ -1013,7 +1034,7 @@ def get_window_extent(self, renderer=None):
10131034 return bbox .transformed (self .get_transform ())
10141035
10151036 def make_image (self , renderer , magnification = 1.0 , unsampled = False ):
1016- q , _ = self ._container . query ( _get_graph ( self . axes ))
1037+ q = self ._query
10171038 x1 , x2 = q ["x" ]
10181039 y1 , y2 = q ["y" ]
10191040
@@ -1053,8 +1074,7 @@ def set_extent(self, extent, **kwargs):
10531074 state is not changed, so a subsequent call to `.Axes.autoscale_view`
10541075 will redo the autoscaling in accord with `~.Axes.dataLim`.
10551076 """
1056- if not isinstance (self ._container , ImageContainer ):
1057- raise TypeError ("Cannot use 'set_extent' on custom container types" )
1077+ check_container (self , ImageContainer , "'set_extent'" )
10581078
10591079 if extent is None :
10601080 sz = self .get_size ()
@@ -1101,7 +1121,7 @@ def _update_autolims(self, xmin, xmax, ymin, ymax):
11011121
11021122 def get_extent (self ):
11031123 """Return the image extent as tuple (left, right, bottom, top)."""
1104- q , _ = self ._container . query ( _get_graph ( self . axes ))
1124+ q = self ._query
11051125 x = q ["x" ]
11061126 y = q ["y" ]
11071127 return x [0 ], x [- 1 ], y [0 ], y [- 1 ]
@@ -1176,7 +1196,7 @@ def make_image(self, renderer, magnification=1.0, unsampled=False):
11761196 if unsampled :
11771197 raise ValueError ('unsampled not supported on NonUniformImage' )
11781198
1179- q , _ = self ._container . query ( _get_graph ( self . axes ))
1199+ q = self ._query
11801200 Ax = q ["x" ]
11811201 Ay = q ["y" ]
11821202
@@ -1262,8 +1282,7 @@ def set_data(self, x, y, A):
12621282 (M, N) `~numpy.ndarray` or masked array of values to be
12631283 colormapped, or (M, N, 3) RGB array, or (M, N, 4) RGBA array.
12641284 """
1265- if not isinstance (self ._container , NonUniformImageContainer ):
1266- raise TypeError ("Cannot use 'set_data' on custom container types" )
1285+ check_container (self , NonUniformImageContainer , "'set_data'" )
12671286 A = self ._normalize_image_array (A )
12681287 x = np .array (x , np .float32 )
12691288 y = np .array (y , np .float32 )
@@ -1308,7 +1327,7 @@ def set_cmap(self, cmap):
13081327
13091328 def get_cursor_data (self , event ):
13101329 # docstring inherited
1311- q , _ = self ._container . query ( _get_graph ( self . axes ))
1330+ q = self ._query
13121331 Ax = q ["x" ]
13131332 Ay = q ["y" ]
13141333 A = q ["image" ]
@@ -1379,7 +1398,7 @@ def make_image(self, renderer, magnification=1.0, unsampled=False):
13791398 if unsampled :
13801399 raise ValueError ('unsampled not supported on PcolorImage' )
13811400
1382- q , _ = self ._container . query ( _get_graph ( self . axes ))
1401+ q = self ._query
13831402 Ax = q ["x" ]
13841403 Ay = q ["y" ]
13851404
@@ -1432,8 +1451,7 @@ def set_data(self, x, y, A):
14321451 - (M, N, 3): RGB array
14331452 - (M, N, 4): RGBA array
14341453 """
1435- if not isinstance (self ._container , PcolorImageContainer ):
1436- raise TypeError ("Cannot use 'set_data' on custom container types" )
1454+ check_container (self , PcolorImageContainer , "'set_data'" )
14371455 A = self ._normalize_image_array (A )
14381456 x = np .arange (0. , A .shape [1 ] + 1 ) if x is None else np .array (x , float ).ravel ()
14391457 y = np .arange (0. , A .shape [0 ] + 1 ) if y is None else np .array (y , float ).ravel ()
@@ -1459,7 +1477,7 @@ def set_array(self, *args):
14591477
14601478 def get_cursor_data (self , event ):
14611479 # docstring inherited
1462- q , _ = self ._container . query ( _get_graph ( self . axes ))
1480+ q = self ._query
14631481 Ax = q ["x" ]
14641482 Ay = q ["y" ]
14651483 A = q ["image" ]
@@ -1514,7 +1532,7 @@ def __init__(self, fig,
15141532
15151533 def get_extent (self ):
15161534 """Return the image extent as tuple (left, right, bottom, top)."""
1517- q , _ = self ._container . query ( _get_graph ( self . axes ))
1535+ q = self ._query
15181536 ox = q ["x" ]
15191537 oy = q ["y" ]
15201538 A = q ["image" ]
@@ -1525,7 +1543,7 @@ def get_extent(self):
15251543
15261544 def make_image (self , renderer , magnification = 1.0 , unsampled = False ):
15271545 # docstring inherited
1528- q , _ = self ._container . query ( _get_graph ( self . axes ))
1546+ q = self ._query
15291547 ox = q ["x" ]
15301548 oy = q ["y" ]
15311549 A = q ["image" ]
@@ -1647,7 +1665,7 @@ def contains(self, mouseevent):
16471665
16481666 def make_image (self , renderer , magnification = 1.0 , unsampled = False ):
16491667 # docstring inherited
1650- q , _ = self ._container . query ( _get_graph ( self . axes ))
1668+ q = self ._query
16511669 A = q ["image" ]
16521670
16531671 width , height = renderer .get_canvas_width_height ()
0 commit comments