Skip to content

Commit b9df5e7

Browse files
committed
Fix default theta tick locations for non-full-circle polar plots.
Currently, non-full-circle polar plots may (depending on the axes size) put theta ticks at positions that make sense for linear plots, but are a bit weird for polar plots (e.g. 50° or 25°). Instead, prefer "standard" angles (90°, 45°, 30°, 15°, 10°). For really small axes, there's still a problem because a single tick may end up at 150°, but fixing the machinery to allow 15° while rejecting 150° would be trickier. (Likewise, really thin slivers likely want ticks at 0.5° steps rather than 0.45° :/)
1 parent c7ebf91 commit b9df5e7

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Default theta tick locations for non-full-circle polar plots have changed
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
For polar plots that don't cover a full circle, the default theta tick
4+
locations are now at multiples of 10°, 15°, 30°, 45°, 90°, rather than using
5+
values that mostly make sense for linear plots (20°, 25°, etc.).

lib/matplotlib/projections/polar.py

+5
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,11 @@ def cla(self):
390390

391391
def _set_scale(self, value, **kwargs):
392392
super()._set_scale(value, **kwargs)
393+
if value == "linear": # Should always be the case.
394+
# LinearScale.set_default_locators_and_formatters just set the
395+
# major locator to be an AutoLocator, so we customize it here to
396+
# have ticks at sensible degree multiples.
397+
self.get_major_locator().set_params(steps=[1, 1.5, 3, 4.5, 9, 10])
393398
self._wrap_locator_formatter()
394399

395400
def _copy_tick_props(self, src, dest):

lib/matplotlib/tests/test_polar.py

+16
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,8 @@ def test_polar_theta_limits():
249249
direction=DIRECTIONS[i % len(DIRECTIONS)],
250250
rotation='auto')
251251
ax.yaxis.set_tick_params(label2On=True, rotation='auto')
252+
ax.xaxis.get_major_locator().base.set_params( # backcompat
253+
steps=[1, 2, 2.5, 5, 10])
252254

253255

254256
@check_figures_equal(extensions=["png"])
@@ -357,3 +359,17 @@ def test_thetalim_args():
357359
assert tuple(np.radians((ax.get_thetamin(), ax.get_thetamax()))) == (0, 1)
358360
ax.set_thetalim((2, 3))
359361
assert tuple(np.radians((ax.get_thetamin(), ax.get_thetamax()))) == (2, 3)
362+
363+
364+
def test_default_thetalocator():
365+
# Ideally we would check AAAABBC, but the smallest axes currently puts a
366+
# single tick at 150° because MaxNLocator doesn't have a way to accept 15°
367+
# while rejecting 150°.
368+
fig, axs = plt.subplot_mosaic(
369+
"AAAABB.", subplot_kw={"projection": "polar"})
370+
for ax in axs.values():
371+
ax.set_thetalim(0, np.pi)
372+
for ax in axs.values():
373+
ticklocs = np.degrees(ax.xaxis.get_majorticklocs()).tolist()
374+
assert pytest.approx(90) in ticklocs
375+
assert pytest.approx(100) not in ticklocs

0 commit comments

Comments
 (0)