Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 0666c59

Browse filesBrowse files
authored
Merge pull request #20949 from anntzer/smd
Improve formatting of imshow() cursor data independently of colorbar.
2 parents 45d0034 + decda3b commit 0666c59
Copy full SHA for 0666c59

File tree

5 files changed

+36
-39
lines changed
Filter options

5 files changed

+36
-39
lines changed

‎lib/matplotlib/artist.py

Copy file name to clipboardExpand all lines: lib/matplotlib/artist.py
+8-6Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
import matplotlib as mpl
1414
from . import _api, cbook
15+
from .cm import ScalarMappable
1516
from .path import Path
1617
from .transforms import (Bbox, IdentityTransform, Transform, TransformedBbox,
1718
TransformedPatchPath, TransformedPath)
@@ -1261,17 +1262,18 @@ def format_cursor_data(self, data):
12611262
--------
12621263
get_cursor_data
12631264
"""
1264-
if np.ndim(data) == 0 and getattr(self, "colorbar", None):
1265+
if np.ndim(data) == 0 and isinstance(self, ScalarMappable):
12651266
# This block logically belongs to ScalarMappable, but can't be
12661267
# implemented in it because most ScalarMappable subclasses inherit
12671268
# from Artist first and from ScalarMappable second, so
12681269
# Artist.format_cursor_data would always have precedence over
12691270
# ScalarMappable.format_cursor_data.
1270-
return (
1271-
"["
1272-
+ cbook.strip_math(
1273-
self.colorbar.formatter.format_data_short(data)).strip()
1274-
+ "]")
1271+
n = self.cmap.N
1272+
# Midpoints of neighboring color intervals.
1273+
neighbors = self.norm.inverse(
1274+
(int(self.norm(data) * n) + np.array([0, 1])) / n)
1275+
delta = abs(neighbors - data).max()
1276+
return "[{:-#.{}g}]".format(data, cbook._g_sig_digits(data, delta))
12751277
else:
12761278
try:
12771279
data[0]

‎lib/matplotlib/cbook/__init__.py

Copy file name to clipboardExpand all lines: lib/matplotlib/cbook/__init__.py
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import functools
1313
import gzip
1414
import itertools
15+
import math
1516
import operator
1617
import os
1718
from pathlib import Path
@@ -2206,6 +2207,23 @@ def _format_approx(number, precision):
22062207
return f'{number:.{precision}f}'.rstrip('0').rstrip('.') or '0'
22072208

22082209

2210+
def _g_sig_digits(value, delta):
2211+
"""
2212+
Return the number of significant digits to %g-format *value*, assuming that
2213+
it is known with an error of *delta*.
2214+
"""
2215+
# If e.g. value = 45.67 and delta = 0.02, then we want to round to 2 digits
2216+
# after the decimal point (floor(log10(0.02)) = -2); 45.67 contributes 2
2217+
# digits before the decimal point (floor(log10(45.67)) + 1 = 2): the total
2218+
# is 4 significant digits. A value of 0 contributes 1 "digit" before the
2219+
# decimal point.
2220+
# For inf or nan, the precision doesn't matter.
2221+
return max(
2222+
0,
2223+
(math.floor(math.log10(abs(value))) + 1 if value else 1)
2224+
- math.floor(math.log10(delta))) if math.isfinite(value) else 0
2225+
2226+
22092227
def _unikey_or_keysym_to_mplkey(unikey, keysym):
22102228
"""
22112229
Convert a Unicode key or X keysym to a Matplotlib key name.

‎lib/matplotlib/projections/polar.py

Copy file name to clipboardExpand all lines: lib/matplotlib/projections/polar.py
+4-10Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,16 +1399,10 @@ def format_coord(self, theta, r):
13991399
# (as for linear axes), but for theta, use f-formatting as scientific
14001400
# notation doesn't make sense and the trailing dot is ugly.
14011401
def format_sig(value, delta, opt, fmt):
1402-
digits_post_decimal = math.floor(math.log10(delta))
1403-
digits_offset = (
1404-
# For "f", only count digits after decimal point.
1405-
0 if fmt == "f"
1406-
# For "g", offset by digits before the decimal point.
1407-
else math.floor(math.log10(abs(value))) + 1 if value
1408-
# For "g", 0 contributes 1 "digit" before the decimal point.
1409-
else 1)
1410-
fmt_prec = max(0, digits_offset - digits_post_decimal)
1411-
return f"{value:-{opt}.{fmt_prec}{fmt}}"
1402+
# For "f", only count digits after decimal point.
1403+
prec = (max(0, -math.floor(math.log10(delta))) if fmt == "f" else
1404+
cbook._g_sig_digits(value, delta))
1405+
return f"{value:-{opt}.{prec}{fmt}}"
14121406

14131407
return ('\N{GREEK SMALL LETTER THETA}={}\N{GREEK SMALL LETTER PI} '
14141408
'({}\N{DEGREE SIGN}), r={}').format(

‎lib/matplotlib/tests/test_image.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_image.py
+5-13Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,11 @@ def test_cursor_data():
337337

338338

339339
@pytest.mark.parametrize(
340-
"data, text_without_colorbar, text_with_colorbar", [
341-
([[10001, 10000]], "[1e+04]", "[10001]"),
342-
([[.123, .987]], "[0.123]", "[0.123]"),
340+
"data, text", [
341+
([[10001, 10000]], "[10001.000]"),
342+
([[.123, .987]], "[0.123]"),
343343
])
344-
def test_format_cursor_data(data, text_without_colorbar, text_with_colorbar):
344+
def test_format_cursor_data(data, text):
345345
from matplotlib.backend_bases import MouseEvent
346346

347347
fig, ax = plt.subplots()
@@ -350,15 +350,7 @@ def test_format_cursor_data(data, text_without_colorbar, text_with_colorbar):
350350
xdisp, ydisp = ax.transData.transform([0, 0])
351351
event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
352352
assert im.get_cursor_data(event) == data[0][0]
353-
assert im.format_cursor_data(im.get_cursor_data(event)) \
354-
== text_without_colorbar
355-
356-
fig.colorbar(im)
357-
fig.canvas.draw() # This is necessary to set up the colorbar formatter.
358-
359-
assert im.get_cursor_data(event) == data[0][0]
360-
assert im.format_cursor_data(im.get_cursor_data(event)) \
361-
== text_with_colorbar
353+
assert im.format_cursor_data(im.get_cursor_data(event)) == text
362354

363355

364356
@image_comparison(['image_clip'], style='mpl20')

‎lib/matplotlib/ticker.py

Copy file name to clipboardExpand all lines: lib/matplotlib/ticker.py
+1-10Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -655,16 +655,7 @@ def format_data_short(self, value):
655655
# Rough approximation: no more than 1e4 divisions.
656656
a, b = self.axis.get_view_interval()
657657
delta = (b - a) / 1e4
658-
# If e.g. value = 45.67 and delta = 0.02, then we want to round to
659-
# 2 digits after the decimal point (floor(log10(0.02)) = -2);
660-
# 45.67 contributes 2 digits before the decimal point
661-
# (floor(log10(45.67)) + 1 = 2): the total is 4 significant digits.
662-
# A value of 0 contributes 1 "digit" before the decimal point.
663-
sig_digits = max(
664-
0,
665-
(math.floor(math.log10(abs(value))) + 1 if value else 1)
666-
- math.floor(math.log10(delta)))
667-
fmt = f"%-#.{sig_digits}g"
658+
fmt = "%-#.{}g".format(cbook._g_sig_digits(value, delta))
668659
return self._format_maybe_minus_and_locale(fmt, value)
669660

670661
def format_data(self, value):

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.