@@ -59,6 +59,7 @@ def __init__(self,axes,spine_type,path,**kwargs):
59
59
self .set_transform (self .axes .transData ) # default transform
60
60
61
61
self ._bounds = None # default bounds
62
+ self ._smart_bounds = False
62
63
63
64
# Defer initial position determination. (Not much support for
64
65
# non-rectangular axes is currently implemented, and this lets
@@ -78,6 +79,20 @@ def __init__(self,axes,spine_type,path,**kwargs):
78
79
# Note: This cannot be calculated until this is added to an Axes
79
80
self ._patch_transform = mtransforms .IdentityTransform ()
80
81
82
+ def set_smart_bounds (self ,value ):
83
+ """set the spine and associated axis to have smart bounds"""
84
+ self ._smart_bounds = value
85
+
86
+ # also set the axis if possible
87
+ if self .spine_type in ('left' ,'right' ):
88
+ self .axes .yaxis .set_smart_bounds (value )
89
+ elif self .spine_type in ('top' ,'bottom' ):
90
+ self .axes .xaxis .set_smart_bounds (value )
91
+
92
+ def get_smart_bounds (self ):
93
+ """get whether the spine has smart bounds"""
94
+ return self ._smart_bounds
95
+
81
96
def set_patch_circle (self ,center ,radius ):
82
97
"""set the spine to be circular"""
83
98
self ._patch_type = 'circle'
@@ -141,6 +156,26 @@ def cla(self):
141
156
if self .axis is not None :
142
157
self .axis .cla ()
143
158
159
+ def is_frame_like (self ):
160
+ """return True if directly on axes frame
161
+
162
+ This is useful for determining if a spine is the edge of an
163
+ old style MPL plot. If so, this function will return True.
164
+ """
165
+ self ._ensure_position_is_set ()
166
+ position = self ._position
167
+ if cbook .is_string_like (position ):
168
+ if position == 'center' :
169
+ position = ('axes' ,0.5 )
170
+ elif position == 'zero' :
171
+ position = ('data' ,0 )
172
+ assert len (position )== 2 , "position should be 2-tuple"
173
+ position_type , amount = position
174
+ if position_type == 'outward' and amount == 0 :
175
+ return True
176
+ else :
177
+ return False
178
+
144
179
def _adjust_location (self ):
145
180
"""automatically set spine bounds to the view interval"""
146
181
@@ -154,6 +189,61 @@ def _adjust_location(self):
154
189
low ,high = self .axes .viewLim .intervalx
155
190
else :
156
191
raise ValueError ('unknown spine spine_type: %s' % self .spine_type )
192
+
193
+ if self ._smart_bounds :
194
+ # attempt to set bounds in sophisticated way
195
+ if low > high :
196
+ # handle inverted limits
197
+ low ,high = high ,low
198
+
199
+ viewlim_low = low
200
+ viewlim_high = high
201
+
202
+ del low , high
203
+
204
+ if self .spine_type in ('left' ,'right' ):
205
+ datalim_low ,datalim_high = self .axes .dataLim .intervaly
206
+ ticks = self .axes .get_yticks ()
207
+ elif self .spine_type in ('top' ,'bottom' ):
208
+ datalim_low ,datalim_high = self .axes .dataLim .intervalx
209
+ ticks = self .axes .get_xticks ()
210
+ # handle inverted limits
211
+ ticks = list (ticks )
212
+ ticks .sort ()
213
+ ticks = np .array (ticks )
214
+ if datalim_low > datalim_high :
215
+ datalim_low , datalim_high = datalim_high , datalim_low
216
+
217
+ if datalim_low < viewlim_low :
218
+ # Data extends past view. Clip line to view.
219
+ low = viewlim_low
220
+ else :
221
+ # Data ends before view ends.
222
+ cond = (ticks <= datalim_low ) & (ticks >= viewlim_low )
223
+ tickvals = ticks [cond ]
224
+ if len (tickvals ):
225
+ # A tick is less than or equal to lowest data point.
226
+ low = tickvals [- 1 ]
227
+ else :
228
+ # No tick is available
229
+ low = datalim_low
230
+ low = max (low ,viewlim_low )
231
+
232
+ if datalim_high > viewlim_high :
233
+ # Data extends past view. Clip line to view.
234
+ high = viewlim_high
235
+ else :
236
+ # Data ends before view ends.
237
+ cond = (ticks >= datalim_high ) & (ticks <= viewlim_high )
238
+ tickvals = ticks [cond ]
239
+ if len (tickvals ):
240
+ # A tick is greater than or equal to highest data point.
241
+ high = tickvals [0 ]
242
+ else :
243
+ # No tick is available
244
+ high = datalim_high
245
+ high = min (high ,viewlim_high )
246
+
157
247
else :
158
248
low ,high = self ._bounds
159
249
@@ -316,11 +406,16 @@ def get_spine_transform(self):
316
406
raise ValueError ("unknown spine_transform type: %s" % what )
317
407
318
408
def set_bounds ( self , low , high ):
409
+ """Set the bounds of the spine."""
319
410
if self .spine_type == 'circle' :
320
411
raise ValueError (
321
412
'set_bounds() method incompatible with circular spines' )
322
413
self ._bounds = (low , high )
323
414
415
+ def get_bounds ( self ):
416
+ """Get the bounds of the spine."""
417
+ return self ._bounds
418
+
324
419
@classmethod
325
420
def linear_spine (cls , axes , spine_type , ** kwargs ):
326
421
"""
0 commit comments