Skip to content

Commit 078103e

Browse files
mgeierfs446
andauthored
Register more "clipped" color maps, use viridis_clip as default for level() (#191)
* Register more "clipped" color maps (all mpl's perceptually uniform sequential and RdBu as diverging) * use viridis_clip as default for level() * use coolwarm_clip as default for amplitude() * Mix dark colors with white, bright colors with black * Calculate under/over values with colorspacious * and hard-code these under/over values --------- Co-authored-by: Frank Schultz <[email protected]>
1 parent cd74a17 commit 078103e

File tree

1 file changed

+71
-19
lines changed

1 file changed

+71
-19
lines changed

sfs/plot2d.py

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,79 @@
88
from . import util as _util
99

1010

11-
def _register_cmap_clip(name, original_cmap, alpha):
12-
"""Create a color map with "over" and "under" values."""
13-
from matplotlib.colors import LinearSegmentedColormap
14-
cdata = _plt.cm.datad[original_cmap]
15-
if isinstance(cdata, dict):
16-
cmap = LinearSegmentedColormap(name, cdata)
11+
def _make_extreme(rgba):
12+
"""Make bright colors darker, dark colors brighter, both less saturated."""
13+
# The package `colorspacious` must be installed for this to work:
14+
from colorspacious import cspace_convert
15+
lightness_step = 25
16+
chroma_factor = 0.7
17+
j, c, h = cspace_convert(rgba[:3], 'sRGB1', 'JCh')
18+
if j > 50:
19+
j -= lightness_step
1720
else:
18-
cmap = LinearSegmentedColormap.from_list(name, cdata)
19-
cmap.set_over([alpha * c + 1 - alpha for c in cmap(1.0)[:3]])
20-
cmap.set_under([alpha * c + 1 - alpha for c in cmap(0.0)[:3]])
21+
j += lightness_step
22+
c *= chroma_factor
23+
rgba[:3] = _np.clip(cspace_convert([j, c, h], 'JCh', 'sRGB1'), 0, 1)
24+
return rgba
25+
26+
27+
def _register_cmap_with_extremes(name, original_name, **kwargs):
28+
"""Create a color map with "under" and "over" values."""
29+
cmap = _plt.get_cmap(original_name)
30+
cmap = cmap.with_extremes(**kwargs)
31+
cmap.name = name
2132
_plt.colormaps.register(cmap=cmap)
2233

2334

35+
# The following under/over values have been calculated with _make_extreme().
36+
# They are hard-coded to avoid a dependency on the library "colorspacious".
37+
_register_cmap_with_extremes('cividis_clip', 'cividis',
38+
under=[0.3581123750444155, 0.4308239004832521, 0.5431626919728758, 1.0],
39+
over=[0.748794386079359, 0.6952014568472878, 0.27380570592765713, 1.0])
40+
_register_cmap_with_extremes('cividis_r_clip', 'cividis_r',
41+
under=[0.748794386079359, 0.6952014568472878, 0.27380570592765713, 1.0],
42+
over=[0.3581123750444155, 0.4308239004832521, 0.5431626919728758, 1.0])
43+
_register_cmap_with_extremes('inferno_clip', 'inferno',
44+
under=[0.3223737972210511, 0.3196564508033573, 0.3474201893768059, 1.0],
45+
over=[0.7759331577663429, 0.7815136432099379, 0.5546145677840046, 1.0])
46+
_register_cmap_with_extremes('inferno_r_clip', 'inferno_r',
47+
under=[0.7759331577663429, 0.7815136432099379, 0.5546145677840046, 1.0],
48+
over=[0.3223737972210511, 0.3196564508033573, 0.3474201893768059, 1.0])
49+
_register_cmap_with_extremes('magma_clip', 'magma',
50+
under=[0.3223737972210511, 0.3196564508033573, 0.3474201893768059, 1.0],
51+
over=[0.7755917106347097, 0.7765145738617047, 0.621366899182334, 1.0])
52+
_register_cmap_with_extremes('magma_r_clip', 'magma_r',
53+
under=[0.7755917106347097, 0.7765145738617047, 0.621366899182334, 1.0],
54+
over=[0.3223737972210511, 0.3196564508033573, 0.3474201893768059, 1.0])
55+
_register_cmap_with_extremes('plasma_clip', 'plasma',
56+
under=[0.3425913695445096, 0.42529714344969144, 0.66039452922638, 1.0],
57+
over=[0.723897190872765, 0.7507494961114689, 0.2574503078804632, 1.0])
58+
_register_cmap_with_extremes('plasma_r_clip', 'plasma_r',
59+
under=[0.723897190872765, 0.7507494961114689, 0.2574503078804632, 1.0],
60+
over=[0.3425913695445096, 0.42529714344969144, 0.66039452922638, 1.0])
61+
_register_cmap_with_extremes('viridis_clip', 'viridis',
62+
under=[0.536623905475994, 0.3775029064902613, 0.5655492658877974, 1.0],
63+
over=[0.7453792828268919, 0.6916769483054797, 0.24219807423955453, 1.0])
64+
_register_cmap_with_extremes('viridis_r_clip', 'viridis_r',
65+
under=[0.7453792828268919, 0.6916769483054797, 0.24219807423955453, 1.0],
66+
over=[0.536623905475994, 0.3775029064902613, 0.5655492658877974, 1.0])
67+
68+
_register_cmap_with_extremes('RdBu_clip', 'RdBu',
69+
under=[0.6931181505544421, 0.3643024937396605, 0.40355267940576434, 1.0],
70+
over=[0.3844199587527661, 0.4705632423745359, 0.597949800233206, 1.0])
71+
_register_cmap_with_extremes('RdBu_r_clip', 'RdBu_r',
72+
under=[0.3844199587527661, 0.4705632423745359, 0.597949800233206, 1.0],
73+
over=[0.6931181505544421, 0.3643024937396605, 0.40355267940576434, 1.0])
74+
2475
# The 'coolwarm' colormap is based on the paper
2576
# "Diverging Color Maps for Scientific Visualization" by Kenneth Moreland
26-
# http://www.sandia.gov/~kmorel/documents/ColorMaps/
27-
# already registered in MPL 3.9.0
28-
try:
29-
_register_cmap_clip('coolwarm_clip', 'coolwarm', 0.7)
30-
except ImportError:
31-
pass
77+
# https://www.kennethmoreland.com/color-maps/ColorMapsExpanded.pdf
78+
_register_cmap_with_extremes('coolwarm_clip', 'coolwarm',
79+
under=[0.510515040101537, 0.5812838578665308, 0.8594377816482693, 1.0],
80+
over=[0.9464304571740522, 0.43619922642510556, 0.4340300540797168, 1.0])
81+
_register_cmap_with_extremes('coolwarm_r_clip', 'coolwarm_r',
82+
under=[0.9464304571740522, 0.43619922642510556, 0.4340300540797168, 1.0],
83+
over=[0.510515040101537, 0.5812838578665308, 0.8594377816482693, 1.0])
3284

3385

3486
def _register_cmap_transparent(name, color):
@@ -180,7 +232,7 @@ def _visible_secondarysources(x0, n0, grid):
180232
"""Determine secondary sources which lie within *grid*."""
181233
x, y = _util.as_xyz_components(grid[:2])
182234
idx = _np.where((x0[:, 0] > x.min()) & (x0[:, 0] < x.max()) &
183-
(x0[:, 1] > y.min()) & (x0[:, 1] < x.max()))
235+
(x0[:, 1] > y.min()) & (x0[:, 1] < x.max()))
184236
idx = _np.squeeze(idx)
185237

186238
return x0[idx, :], n0[idx, :]
@@ -325,8 +377,8 @@ def amplitude(p, grid, *, xnorm=None, cmap='coolwarm_clip',
325377
return im
326378

327379

328-
def level(p, grid, *, xnorm=None, power=False, cmap=None, vmax=3, vmin=-50,
329-
colorbar_kwargs=None, **kwargs):
380+
def level(p, grid, *, xnorm=None, power=False, cmap='viridis_clip',
381+
vmax=3, vmin=-50, colorbar_kwargs=None, **kwargs):
330382
"""Two-dimensional plot of level (dB) of sound field.
331383
332384
Takes the same parameters as `sfs.plot2d.amplitude()`.
@@ -383,7 +435,7 @@ def level_contour(p, grid, *, xnorm=None, power=False,
383435
def particles(x, *, trim=None, ax=None, xlabel='x (m)', ylabel='y (m)',
384436
edgecolors=None, marker='.', s=15, **kwargs):
385437
"""Plot particle positions as scatter plot.
386-
438+
387439
Parameters
388440
----------
389441
x : triple or pair of array_like

0 commit comments

Comments
 (0)