Skip to content

Commit cbaee4a

Browse files
committed
ENH: Allow setting an "origin" radius for PolarAxes.
This means that the minimum radius can be offset to not occur right at the middle of the plot.
1 parent 2b33d7f commit cbaee4a

File tree

2 files changed

+69
-19
lines changed

2 files changed

+69
-19
lines changed

lib/matplotlib/projections/polar.py

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def transform_non_affine(self, tr):
5454
t += self._axis.get_theta_offset()
5555

5656
if self._use_rmin and self._axis is not None:
57-
r = r - self._axis.viewLim.ymin
57+
r = r - self._axis.get_rorigin()
5858
mask = r < 0
5959
x[:] = np.where(mask, np.nan, r * np.cos(t))
6060
y[:] = np.where(mask, np.nan, r * np.sin(t))
@@ -146,7 +146,7 @@ def transform_non_affine(self, xy):
146146
theta %= 2 * np.pi
147147

148148
if self._use_rmin and self._axis is not None:
149-
r += self._axis.viewLim.ymin
149+
r += self._axis.get_rorigin()
150150

151151
return np.concatenate((theta, r), 1)
152152
transform_non_affine.__doc__ = \
@@ -198,13 +198,14 @@ def __call__(self):
198198
show_all = True
199199
# Ensure previous behaviour with full circle views.
200200
if self._axes:
201-
rmin = self._axes.get_rmin()
202-
show_all = False
201+
rorigin = self._axes.get_rorigin()
202+
if self._axes.get_rmin() <= rorigin:
203+
show_all = False
203204

204205
if show_all:
205206
return self.base()
206207
else:
207-
return [tick for tick in self.base() if tick > rmin]
208+
return [tick for tick in self.base() if tick > rorigin]
208209

209210
def autoscale(self):
210211
return self.base.autoscale()
@@ -259,11 +260,15 @@ def cla(self):
259260

260261
self.grid(rcParams['polaraxes.grid'])
261262
self.xaxis.set_ticks_position('none')
263+
inner = self.spines.get('inner', None)
264+
if inner:
265+
inner.set_visible(False)
262266
self.yaxis.set_ticks_position('none')
263267
self.yaxis.set_tick_params(label1On=True)
264268
# Why do we need to turn on yaxis tick labels, but
265269
# xaxis tick labels are already on?
266270

271+
self.set_rorigin(None)
267272
self.set_theta_offset(self._default_theta_offset)
268273
self.set_theta_direction(self._default_theta_direction)
269274

@@ -307,6 +312,8 @@ def _set_lim_and_transforms(self):
307312
self.transProjection = self.PolarTransform(
308313
self,
309314
_apply_theta_transforms=False)
315+
# Add dependency on rorigin.
316+
self.transProjection.set_children(self._originViewLim)
310317

311318
# This one is not aware of rmin
312319
self.transPureProjection = self.PolarTransform(
@@ -316,7 +323,8 @@ def _set_lim_and_transforms(self):
316323

317324
# An affine transformation on the data, generally to limit the
318325
# range of the axes
319-
self.transProjectionAffine = self.PolarAffine(self.transScale, self.viewLim)
326+
self.transProjectionAffine = self.PolarAffine(self.transScale,
327+
self._originViewLim)
320328

321329
# The complete data transformation stack -- from data all the
322330
# way to display coordinates
@@ -397,24 +405,35 @@ def get_yaxis_text2_transform(self, pad):
397405
else:
398406
return self._yaxis_text_transform, 'bottom', 'right'
399407

400-
def _gen_axes_patch(self):
401-
return mpatches.Circle((0.5, 0.5), 0.5)
408+
def draw(self, *args, **kwargs):
409+
rmin, rmax = self.viewLim.intervaly
410+
rorigin = self.get_rorigin()
411+
inner = self.spines.get('inner', None)
402412

403-
def _gen_axes_spines(self):
404-
return {'polar':mspines.Spine.circular_spine(self,
405-
(0.5, 0.5), 0.5)}
413+
if isinstance(self.patch, mpatches.Wedge):
414+
# Backwards-compatibility: Any subclassed Axes might override the
415+
# patch to not be the Wedge that PolarAxes uses.
416+
if rorigin < rmin:
417+
width = (rmax - rmin) / (rmax - rorigin) * 0.5
418+
else:
419+
width = 0.5
420+
self.patch.set_width(width)
406421

407-
def set_rmax(self, rmax):
408-
self.viewLim.y1 = rmax
422+
inner_width = 0.5 - width
423+
if inner:
424+
inner.set_patch_circle((0.5, 0.5), inner_width)
425+
inner.set_visible(inner_width != 0.0)
409426

410-
def get_rmax(self):
411-
return self.viewLim.ymax
427+
Axes.draw(self, *args, **kwargs)
412428

413-
def set_rmin(self, rmin):
414-
self.viewLim.y0 = rmin
429+
def _gen_axes_patch(self):
430+
return mpatches.Wedge((0.5, 0.5), 0.5, 0.0, 360.0)
415431

416-
def get_rmin(self):
417-
return self.viewLim.ymin
432+
def _gen_axes_spines(self):
433+
return {'polar': mspines.Spine.circular_spine(self,
434+
(0.5, 0.5), 0.5),
435+
'inner': mspines.Spine.circular_spine(self,
436+
(0.5, 0.5), 0.0)}
418437

419438
def set_theta_offset(self, offset):
420439
"""
@@ -481,6 +500,24 @@ def get_theta_direction(self):
481500
"""
482501
return self._direction.get_matrix()[0, 0]
483502

503+
def set_rmax(self, rmax):
504+
self.viewLim.y1 = rmax
505+
506+
def get_rmax(self):
507+
return self.viewLim.ymax
508+
509+
def set_rmin(self, rmin):
510+
self.viewLim.y0 = rmin
511+
512+
def get_rmin(self):
513+
return self.viewLim.ymin
514+
515+
def set_rorigin(self, rorigin):
516+
self._originViewLim.locked_y0 = rorigin
517+
518+
def get_rorigin(self):
519+
return self._originViewLim.y0
520+
484521
def set_rlim(self, *args, **kwargs):
485522
if 'rmin' in kwargs:
486523
kwargs['ymin'] = kwargs.pop('rmin')

lib/matplotlib/tests/test_axes.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,19 @@ def test_polar_negative_rmin():
636636
ax.set_rmin(-3.0)
637637

638638

639+
@image_comparison(baseline_images=['polar_rorigin'], style='default')
640+
def test_polar_rorigin():
641+
r = np.arange(0, 3.0, 0.01)
642+
theta = 2*np.pi*r
643+
644+
fig = plt.figure()
645+
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)
646+
ax.plot(theta, r)
647+
ax.set_rmax(2.0)
648+
ax.set_rmin(0.5)
649+
ax.set_rorigin(0.0)
650+
651+
639652
@image_comparison(baseline_images=['polar_theta_position'])
640653
def test_polar_theta_position():
641654
r = np.arange(0, 3.0, 0.01)

0 commit comments

Comments
 (0)