Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7b0e1cc

Browse files
committed
For polar plots, report cursor position with correct precision.
... similar to what's done for cartesian plots (in ScalarFormatter.format_data_short).
1 parent 303873f commit 7b0e1cc

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

lib/matplotlib/projections/polar.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from collections import OrderedDict
2+
import math
23
import types
34

45
import numpy as np
@@ -187,6 +188,7 @@ class ThetaFormatter(mticker.Formatter):
187188
Used to format the *theta* tick labels. Converts the native
188189
unit of radians into degrees and adds a degree symbol.
189190
"""
191+
190192
def __call__(self, x, pos=None):
191193
vmin, vmax = self.axis.get_view_interval()
192194
d = np.rad2deg(abs(vmax - vmin))
@@ -1403,11 +1405,40 @@ def set_rgrids(self, radii, labels=None, angle=None, fmt=None, **kwargs):
14031405

14041406
def format_coord(self, theta, r):
14051407
# docstring inherited
1408+
screen_xy = self.transData.transform((theta, r))
1409+
screen_xys = screen_xy + np.stack(
1410+
np.meshgrid([-1, 0, 1], [-1, 0, 1])).reshape((2, -1)).T
1411+
ts, rs = self.transData.inverted().transform(screen_xys).T
1412+
delta_t = abs((ts - theta + np.pi) % (2 * np.pi) - np.pi).max()
1413+
delta_t_halfturns = delta_t / np.pi
1414+
delta_t_degrees = delta_t_halfturns * 180
1415+
delta_r = abs(rs - r).max()
14061416
if theta < 0:
14071417
theta += 2 * np.pi
1408-
theta /= np.pi
1409-
return ('\N{GREEK SMALL LETTER THETA}=%0.3f\N{GREEK SMALL LETTER PI} '
1410-
'(%0.3f\N{DEGREE SIGN}), r=%0.3f') % (theta, theta * 180.0, r)
1418+
theta_halfturns = theta / np.pi
1419+
theta_degrees = theta_halfturns * 180
1420+
1421+
# See ScalarFormatter.format_data_short. For r, use #g-formatting
1422+
# (as for linear axes), but for theta, use f-formatting as scientific
1423+
# notation doesn't make sense and the trailing dot is ugly.
1424+
def format_sig(value, delta, opt, fmt):
1425+
digits_post_decimal = math.floor(math.log10(delta))
1426+
digits_offset = (
1427+
# For "f", only count digits after decimal point.
1428+
0 if fmt == "f"
1429+
# For "g", offset by digits before the decimal point.
1430+
else math.floor(math.log10(abs(value))) + 1 if value
1431+
# For "g", 0 contributes 1 "digit" before the decimal point.
1432+
else 1)
1433+
fmt_prec = max(0, digits_offset - digits_post_decimal)
1434+
return f"{value:-{opt}.{fmt_prec}{fmt}}"
1435+
1436+
return ('\N{GREEK SMALL LETTER THETA}={}\N{GREEK SMALL LETTER PI} '
1437+
'({}\N{DEGREE SIGN}), r={}').format(
1438+
format_sig(theta_halfturns, delta_t_halfturns, "", "f"),
1439+
format_sig(theta_degrees, delta_t_degrees, "", "f"),
1440+
format_sig(r, delta_r, "#", "g"),
1441+
)
14111442

14121443
def get_data_ratio(self):
14131444
"""

lib/matplotlib/tests/test_polar.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,17 @@ def test_shared_polar_keeps_ticklabels():
402402
fig.canvas.draw()
403403
assert axs[0, 1].xaxis.majorTicks[0].get_visible()
404404
assert axs[0, 1].yaxis.majorTicks[0].get_visible()
405+
406+
407+
def test_cursor_precision():
408+
ax = plt.subplot(projection="polar")
409+
# Higher radii correspond to higher theta-precisions.
410+
assert ax.format_coord(0, 0) == "θ=0π (0°), r=0.000"
411+
assert ax.format_coord(0, .1) == "θ=0.00π (0°), r=0.100"
412+
assert ax.format_coord(0, 1) == "θ=0.000π (0.0°), r=1.000"
413+
assert ax.format_coord(1, 0) == "θ=0.3π (57°), r=0.000"
414+
assert ax.format_coord(1, .1) == "θ=0.32π (57°), r=0.100"
415+
assert ax.format_coord(1, 1) == "θ=0.318π (57.3°), r=1.000"
416+
assert ax.format_coord(2, 0) == "θ=0.6π (115°), r=0.000"
417+
assert ax.format_coord(2, .1) == "θ=0.64π (115°), r=0.100"
418+
assert ax.format_coord(2, 1) == "θ=0.637π (114.6°), r=1.000"

0 commit comments

Comments
 (0)