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

Skip to content

Commit be13e92

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 cd33ed2 commit be13e92

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))
@@ -1396,11 +1398,40 @@ def set_rgrids(self, radii, labels=None, angle=None, fmt=None, **kwargs):
13961398

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

14051436
def get_data_ratio(self):
14061437
"""

lib/matplotlib/tests/test_polar.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,3 +357,17 @@ def test_thetalim_args():
357357
assert tuple(np.radians((ax.get_thetamin(), ax.get_thetamax()))) == (0, 1)
358358
ax.set_thetalim((2, 3))
359359
assert tuple(np.radians((ax.get_thetamin(), ax.get_thetamax()))) == (2, 3)
360+
361+
362+
def test_cursor_precision():
363+
ax = plt.subplot(projection="polar")
364+
# Higher radii correspond to higher theta-precisions.
365+
assert ax.format_coord(0, 0) == "θ=0π (0°), r=0.000"
366+
assert ax.format_coord(0, .1) == "θ=0.00π (0°), r=0.100"
367+
assert ax.format_coord(0, 1) == "θ=0.000π (0.0°), r=1.000"
368+
assert ax.format_coord(1, 0) == "θ=0.3π (57°), r=0.000"
369+
assert ax.format_coord(1, .1) == "θ=0.32π (57°), r=0.100"
370+
assert ax.format_coord(1, 1) == "θ=0.318π (57.3°), r=1.000"
371+
assert ax.format_coord(2, 0) == "θ=0.6π (115°), r=0.000"
372+
assert ax.format_coord(2, .1) == "θ=0.64π (115°), r=0.100"
373+
assert ax.format_coord(2, 1) == "θ=0.637π (114.6°), r=1.000"

0 commit comments

Comments
 (0)