11import itertools
2- from typing import Type , List
2+ from typing import Type , List , Optional , Callable
33from matplotlib .axes import Axes
44from matplotlib .transforms import Bbox
55import matplotlib .docstring as docstring
66from matplotview ._transform_renderer import _TransformRenderer
77from matplotlib .artist import Artist
88from matplotlib .backend_bases import RendererBase
99
10+ DEFAULT_RENDER_DEPTH = 10
11+
1012class BoundRendererArtist :
1113 def __init__ (self , artist : Artist , renderer : RendererBase , clip_box : Bbox ):
1214 self ._artist = artist
@@ -66,17 +68,17 @@ class ViewAxesImpl(axes_class):
6668 require Artists to be plotted twice.
6769 """
6870 __module__ = axes_class .__module__
69- # The number of allowed recursions in the draw method
70- MAX_RENDER_DEPTH = 5
7171
7272 def __init__ (
7373 self ,
7474 axes_to_view : Axes ,
7575 * args ,
7676 image_interpolation : str = "nearest" ,
77+ render_depth : int = DEFAULT_RENDER_DEPTH ,
78+ filter_function : Optional [Callable [[Artist ], bool ]] = None ,
7779 ** kwargs
7880 ):
79- """
81+ f """
8082 Construct a new view axes.
8183
8284 Parameters
@@ -96,6 +98,17 @@ def __init__(
9698 'nearest'. This determines the interpolation used when
9799 attempting to render a view of an image.
98100
101+ render_depth: int, positive, defaults to 10
102+ The number of recursive draws allowed for this view, this can
103+ happen if the view is a child of the axes (such as an inset
104+ axes) or if two views point at each other. Defaults to 10.
105+
106+ filter_function: callable(Artist) -> bool or None
107+ An optional filter function, which can be used to select what
108+ artists are drawn by the view. If the function returns True,
109+ the element is drawn, otherwise it isn't. Defaults to None,
110+ or drawing all artists.
111+
99112 **kwargs
100113 Other optional keyword arguments supported by the Axes
101114 constructor this ViewAxes wraps:
@@ -108,15 +121,29 @@ def __init__(
108121 The new zoom view axes instance...
109122 """
110123 super ().__init__ (axes_to_view .figure , * args , ** kwargs )
111- self ._init_vars (axes_to_view , image_interpolation )
124+ self ._init_vars (
125+ axes_to_view , image_interpolation ,
126+ render_depth , filter_function
127+ )
112128
113129 def _init_vars (
114130 self ,
115131 axes_to_view : Axes ,
116- image_interpolation : str = "nearest"
132+ image_interpolation : str ,
133+ render_depth : int ,
134+ filter_function : Optional [Callable [[Artist ], bool ]]
117135 ):
136+ if (render_depth < 1 ):
137+ raise ValueError (f"Render depth of { render_depth } is invalid." )
138+ if (filter_function is None ):
139+ filter_function = lambda a : True
140+ if (not callable (filter_function )):
141+ raise ValueError (f"The filter function must be a callable!" )
142+
118143 self .__view_axes = axes_to_view
119144 self .__image_interpolation = image_interpolation
145+ self .__max_render_depth = render_depth
146+ self .__filter_function = filter_function
120147 self ._render_depth = 0
121148 self .__scale_lines = True
122149 self .__renderer = None
@@ -144,7 +171,7 @@ def get_children(self) -> List[Artist]:
144171 BoundRendererArtist (a , mock_renderer , axes_box )
145172 for a in itertools .chain (
146173 self .__view_axes ._children , self .__view_axes .child_axes
147- ) if (a is not self )
174+ ) if (self . __filter_function ( a ) )
148175 ])
149176
150177 return init_list
@@ -155,7 +182,7 @@ def draw(self, renderer: RendererBase = None):
155182 # It is possible to have two axes which are views of each other
156183 # therefore we track the number of recursions and stop drawing
157184 # at a certain depth
158- if (self ._render_depth >= self .MAX_RENDER_DEPTH ):
185+ if (self ._render_depth >= self .__max_render_depth ):
159186 return
160187 self ._render_depth += 1
161188 # Set the renderer, causing get_children to return the view's
@@ -197,10 +224,15 @@ def from_axes(
197224 cls ,
198225 axes : Axes ,
199226 axes_to_view : Axes ,
200- image_interpolation : str = "nearest"
201- ):
227+ image_interpolation : str = "nearest" ,
228+ render_depth : int = DEFAULT_RENDER_DEPTH ,
229+ filter_function : Optional [Callable [[Artist ], bool ]] = None
230+ ) -> Axes :
202231 axes .__class__ = cls
203- axes ._init_vars (axes_to_view , image_interpolation )
232+ axes ._init_vars (
233+ axes_to_view , image_interpolation ,
234+ render_depth , filter_function
235+ )
204236 return axes
205237
206238 new_name = f"{ ViewAxesImpl .__name__ } [{ axes_class .__name__ } ]"
0 commit comments