Skip to content

Commit 6f10076

Browse files
committed
added whats new entry for CenteredNorm and expanded testing to setters
1 parent ff01e19 commit 6f10076

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
New CenteredNorm for symmetrical data around a center
2+
-----------------------------------------------------
3+
In cases where data is symmetrical around a center, for example, positive and
4+
negative anomalies around a center zero, `~.matplotlib.colors.CenteredNorm`
5+
is a new norm that automatically creates a symmetrical mapping around the
6+
center. This norm is well suited to be combined with a divergent colormap which
7+
uses an unsaturated color in its center.
8+
9+
.. plot::
10+
11+
import matplotlib.pyplot as plt
12+
import numpy as np
13+
from matplotlib.colors import CenteredNorm
14+
15+
np.random.seed(20201004)
16+
data = np.random.normal(size=(3, 4), loc=1)
17+
18+
fig, ax = plt.subplots()
19+
pc = ax.pcolormesh(data, cmap=plt.get_cmap('RdGy'), norm=CenteredNorm())
20+
fig.colorbar(pc)
21+
ax.set_title('data centered around zero')
22+
23+
# add text annotation
24+
for irow, data_row in enumerate(data):
25+
for icol, val in enumerate(data_row):
26+
ax.text(icol + 0.5, irow + 0.5, f'{val:.2f}', color='C0',
27+
size=16, va='center', ha='center')
28+
plt.show()
29+
30+
If the center of symmetry is different from 0, it can be set with the *vcenter*
31+
argument. To manually set the range of `~.matplotlib.colors.CenteredNorm`, use
32+
the *halfrange* argument.
33+
34+
See :doc:`/tutorials/colors/colormapnorms` for an example and more details
35+
about data normalization.

lib/matplotlib/colors.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1342,7 +1342,7 @@ def halfrange(self, halfrange):
13421342
self.vmax = None
13431343
else:
13441344
self._halfrange = abs(halfrange)
1345-
self._set_vmin_vmax()
1345+
#self._set_vmin_vmax()
13461346

13471347
def __call__(self, value, clip=None):
13481348
if self._halfrange is not None:

lib/matplotlib/tests/test_colors.py

+16
Original file line numberDiff line numberDiff line change
@@ -360,25 +360,41 @@ def test_BoundaryNorm():
360360

361361

362362
def test_CenteredNorm():
363+
np.random.seed(0)
364+
363365
# Assert equivalence to symmetrical Normalize.
364366
x = np.random.normal(size=100)
365367
x_maxabs = np.max(np.abs(x))
366368
norm_ref = mcolors.Normalize(vmin=-x_maxabs, vmax=x_maxabs)
367369
norm = mcolors.CenteredNorm()
368370
assert_array_almost_equal(norm_ref(x), norm(x))
371+
369372
# Check that vcenter is in the center of vmin and vmax
370373
# when vcenter is set.
371374
vcenter = int(np.random.normal(scale=50))
372375
norm = mcolors.CenteredNorm(vcenter=vcenter)
373376
norm.autoscale_None([1, 2])
374377
assert norm.vmax + norm.vmin == 2 * vcenter
378+
375379
# Check that halfrange input works correctly.
376380
x = np.random.normal(size=10)
377381
norm = mcolors.CenteredNorm(vcenter=0.5, halfrange=0.5)
378382
assert_array_almost_equal(x, norm(x))
379383
norm = mcolors.CenteredNorm(vcenter=1, halfrange=1)
380384
assert_array_almost_equal(x, 2 * norm(x))
381385

386+
# Check that halfrange input works correctly and use setters.
387+
norm = mcolors.CenteredNorm()
388+
norm.vcenter = 2
389+
norm.halfrange = 2
390+
assert_array_almost_equal(x, 4 * norm(x))
391+
392+
# Check that prior to adding data, setting halfrange first has same effect.
393+
norm = mcolors.CenteredNorm()
394+
norm.halfrange = 2
395+
norm.vcenter = 2
396+
assert_array_almost_equal(x, 4 * norm(x))
397+
382398

383399
@pytest.mark.parametrize("vmin,vmax", [[-1, 2], [3, 1]])
384400
def test_lognorm_invalid(vmin, vmax):

0 commit comments

Comments
 (0)