1
1
import itertools
2
- from typing import Type , List
2
+ from typing import Type , List , Optional , Callable
3
3
from matplotlib .axes import Axes
4
4
from matplotlib .transforms import Bbox
5
5
import matplotlib .docstring as docstring
6
6
from matplotview ._transform_renderer import _TransformRenderer
7
7
from matplotlib .artist import Artist
8
8
from matplotlib .backend_bases import RendererBase
9
9
10
+ DEFAULT_RENDER_DEPTH = 10
11
+
10
12
class BoundRendererArtist :
11
13
def __init__ (self , artist : Artist , renderer : RendererBase , clip_box : Bbox ):
12
14
self ._artist = artist
@@ -66,17 +68,17 @@ class ViewAxesImpl(axes_class):
66
68
require Artists to be plotted twice.
67
69
"""
68
70
__module__ = axes_class .__module__
69
- # The number of allowed recursions in the draw method
70
- MAX_RENDER_DEPTH = 5
71
71
72
72
def __init__ (
73
73
self ,
74
74
axes_to_view : Axes ,
75
75
* args ,
76
76
image_interpolation : str = "nearest" ,
77
+ render_depth : int = DEFAULT_RENDER_DEPTH ,
78
+ filter_function : Optional [Callable [[Artist ], bool ]] = None ,
77
79
** kwargs
78
80
):
79
- """
81
+ f """
80
82
Construct a new view axes.
81
83
82
84
Parameters
@@ -96,6 +98,17 @@ def __init__(
96
98
'nearest'. This determines the interpolation used when
97
99
attempting to render a view of an image.
98
100
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
+
99
112
**kwargs
100
113
Other optional keyword arguments supported by the Axes
101
114
constructor this ViewAxes wraps:
@@ -108,15 +121,29 @@ def __init__(
108
121
The new zoom view axes instance...
109
122
"""
110
123
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
+ )
112
128
113
129
def _init_vars (
114
130
self ,
115
131
axes_to_view : Axes ,
116
- image_interpolation : str = "nearest"
132
+ image_interpolation : str ,
133
+ render_depth : int ,
134
+ filter_function : Optional [Callable [[Artist ], bool ]]
117
135
):
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
+
118
143
self .__view_axes = axes_to_view
119
144
self .__image_interpolation = image_interpolation
145
+ self .__max_render_depth = render_depth
146
+ self .__filter_function = filter_function
120
147
self ._render_depth = 0
121
148
self .__scale_lines = True
122
149
self .__renderer = None
@@ -144,7 +171,7 @@ def get_children(self) -> List[Artist]:
144
171
BoundRendererArtist (a , mock_renderer , axes_box )
145
172
for a in itertools .chain (
146
173
self .__view_axes ._children , self .__view_axes .child_axes
147
- ) if (a is not self )
174
+ ) if (self . __filter_function ( a ) )
148
175
])
149
176
150
177
return init_list
@@ -155,7 +182,7 @@ def draw(self, renderer: RendererBase = None):
155
182
# It is possible to have two axes which are views of each other
156
183
# therefore we track the number of recursions and stop drawing
157
184
# at a certain depth
158
- if (self ._render_depth >= self .MAX_RENDER_DEPTH ):
185
+ if (self ._render_depth >= self .__max_render_depth ):
159
186
return
160
187
self ._render_depth += 1
161
188
# Set the renderer, causing get_children to return the view's
@@ -197,10 +224,15 @@ def from_axes(
197
224
cls ,
198
225
axes : Axes ,
199
226
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 :
202
231
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
+ )
204
236
return axes
205
237
206
238
new_name = f"{ ViewAxesImpl .__name__ } [{ axes_class .__name__ } ]"
0 commit comments