From 599228518c38be47165f94f1d4d790fa35dc0a61 Mon Sep 17 00:00:00 2001 From: Kayran Schmidt <59456929+yumasheta@users.noreply.github.com> Date: Thu, 23 Jun 2022 14:43:35 +0200 Subject: [PATCH] Backport PR #22835: Fix BoundaryNorm cursor data output --- lib/matplotlib/artist.py | 19 +++- lib/matplotlib/tests/test_artist.py | 163 ++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 4 deletions(-) diff --git a/lib/matplotlib/artist.py b/lib/matplotlib/artist.py index 2d71ed6e92c8..aa2fa15ae831 100644 --- a/lib/matplotlib/artist.py +++ b/lib/matplotlib/artist.py @@ -12,6 +12,7 @@ import matplotlib as mpl from . import _api, cbook +from .colors import BoundaryNorm from .cm import ScalarMappable from .path import Path from .transforms import (Bbox, IdentityTransform, Transform, TransformedBbox, @@ -1280,10 +1281,20 @@ def format_cursor_data(self, data): return "[]" normed = self.norm(data) if np.isfinite(normed): - # Midpoints of neighboring color intervals. - neighbors = self.norm.inverse( - (int(self.norm(data) * n) + np.array([0, 1])) / n) - delta = abs(neighbors - data).max() + if isinstance(self.norm, BoundaryNorm): + # not an invertible normalization mapping + cur_idx = np.argmin(np.abs(self.norm.boundaries - data)) + neigh_idx = max(0, cur_idx - 1) + # use max diff to prevent delta == 0 + delta = np.diff( + self.norm.boundaries[neigh_idx:cur_idx + 2] + ).max() + + else: + # Midpoints of neighboring color intervals. + neighbors = self.norm.inverse( + (int(normed * n) + np.array([0, 1])) / n) + delta = abs(neighbors - data).max() g_sig_digits = cbook._g_sig_digits(data, delta) else: g_sig_digits = 3 # Consistent with default below. diff --git a/lib/matplotlib/tests/test_artist.py b/lib/matplotlib/tests/test_artist.py index 74c58d34d991..f5b4e6f84793 100644 --- a/lib/matplotlib/tests/test_artist.py +++ b/lib/matplotlib/tests/test_artist.py @@ -5,6 +5,8 @@ import pytest +from matplotlib import cm +import matplotlib.colors as mcolors import matplotlib.pyplot as plt import matplotlib.patches as mpatches import matplotlib.lines as mlines @@ -374,3 +376,164 @@ class MyArtist4(MyArtist3): pass assert MyArtist4.set is MyArtist3.set + + +def test_format_cursor_data_BoundaryNorm(): + """Test if cursor data is correct when using BoundaryNorm.""" + X = np.empty((3, 3)) + X[0, 0] = 0.9 + X[0, 1] = 0.99 + X[0, 2] = 0.999 + X[1, 0] = -1 + X[1, 1] = 0 + X[1, 2] = 1 + X[2, 0] = 0.09 + X[2, 1] = 0.009 + X[2, 2] = 0.0009 + + # map range -1..1 to 0..256 in 0.1 steps + fig, ax = plt.subplots() + fig.suptitle("-1..1 to 0..256 in 0.1") + norm = mcolors.BoundaryNorm(np.linspace(-1, 1, 20), 256) + img = ax.imshow(X, cmap='RdBu_r', norm=norm) + + labels_list = [ + "[0.9]", + "[1.]", + "[1.]", + "[-1.0]", + "[0.0]", + "[1.0]", + "[0.09]", + "[0.009]", + "[0.0009]", + ] + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.1)) + assert img.format_cursor_data(v) == label + + plt.close() + + # map range -1..1 to 0..256 in 0.01 steps + fig, ax = plt.subplots() + fig.suptitle("-1..1 to 0..256 in 0.01") + cmap = cm.get_cmap('RdBu_r', 200) + norm = mcolors.BoundaryNorm(np.linspace(-1, 1, 200), 200) + img = ax.imshow(X, cmap=cmap, norm=norm) + + labels_list = [ + "[0.90]", + "[0.99]", + "[1.0]", + "[-1.00]", + "[0.00]", + "[1.00]", + "[0.09]", + "[0.009]", + "[0.0009]", + ] + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.01)) + assert img.format_cursor_data(v) == label + + plt.close() + + # map range -1..1 to 0..256 in 0.01 steps + fig, ax = plt.subplots() + fig.suptitle("-1..1 to 0..256 in 0.001") + cmap = cm.get_cmap('RdBu_r', 2000) + norm = mcolors.BoundaryNorm(np.linspace(-1, 1, 2000), 2000) + img = ax.imshow(X, cmap=cmap, norm=norm) + + labels_list = [ + "[0.900]", + "[0.990]", + "[0.999]", + "[-1.000]", + "[0.000]", + "[1.000]", + "[0.090]", + "[0.009]", + "[0.0009]", + ] + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.001)) + assert img.format_cursor_data(v) == label + + plt.close() + + # different testing data set with + # out of bounds values for 0..1 range + X = np.empty((7, 1)) + X[0] = -1.0 + X[1] = 0.0 + X[2] = 0.1 + X[3] = 0.5 + X[4] = 0.9 + X[5] = 1.0 + X[6] = 2.0 + + labels_list = [ + "[-1.0]", + "[0.0]", + "[0.1]", + "[0.5]", + "[0.9]", + "[1.0]", + "[2.0]", + ] + + fig, ax = plt.subplots() + fig.suptitle("noclip, neither") + norm = mcolors.BoundaryNorm( + np.linspace(0, 1, 4, endpoint=True), 256, clip=False, extend='neither') + img = ax.imshow(X, cmap='RdBu_r', norm=norm) + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.33)) + assert img.format_cursor_data(v) == label + + plt.close() + + fig, ax = plt.subplots() + fig.suptitle("noclip, min") + norm = mcolors.BoundaryNorm( + np.linspace(0, 1, 4, endpoint=True), 256, clip=False, extend='min') + img = ax.imshow(X, cmap='RdBu_r', norm=norm) + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.33)) + assert img.format_cursor_data(v) == label + + plt.close() + + fig, ax = plt.subplots() + fig.suptitle("noclip, max") + norm = mcolors.BoundaryNorm( + np.linspace(0, 1, 4, endpoint=True), 256, clip=False, extend='max') + img = ax.imshow(X, cmap='RdBu_r', norm=norm) + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.33)) + assert img.format_cursor_data(v) == label + + plt.close() + + fig, ax = plt.subplots() + fig.suptitle("noclip, both") + norm = mcolors.BoundaryNorm( + np.linspace(0, 1, 4, endpoint=True), 256, clip=False, extend='both') + img = ax.imshow(X, cmap='RdBu_r', norm=norm) + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.33)) + assert img.format_cursor_data(v) == label + + plt.close() + + fig, ax = plt.subplots() + fig.suptitle("clip, neither") + norm = mcolors.BoundaryNorm( + np.linspace(0, 1, 4, endpoint=True), 256, clip=True, extend='neither') + img = ax.imshow(X, cmap='RdBu_r', norm=norm) + for v, label in zip(X.flat, labels_list): + # label = "[{:-#.{}g}]".format(v, cbook._g_sig_digits(v, 0.33)) + assert img.format_cursor_data(v) == label + + plt.close() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy