Skip to content

Commit aeb0522

Browse files
committed
Clean up color, colormap database initialization
1 parent 299cf7e commit aeb0522

File tree

2 files changed

+76
-63
lines changed

2 files changed

+76
-63
lines changed

proplot/colors.py

Lines changed: 72 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2398,6 +2398,59 @@ def autoscale_None(self, z):
23982398
self.vmax = self.vcenter
23992399

24002400

2401+
def _init_color_database():
2402+
"""
2403+
Initialize the subclassed database.
2404+
"""
2405+
if not isinstance(mcolors._colors_full_map, ColorDatabase):
2406+
database = ColorDatabase(mcolors._colors_full_map)
2407+
mcolors._colors_full_map = database
2408+
mcolors.colorConverter.cache = database.cache
2409+
mcolors.colorConverter.colors = database
2410+
2411+
2412+
class _ColorCache(dict):
2413+
"""
2414+
Replacement for the native color cache.
2415+
"""
2416+
# Matplotlib 'color' args are passed to to_rgba, which tries to read
2417+
# directly from cache and if that fails, sanitizes input, which raises
2418+
# error on receiving (colormap, idx) tuple. So we *have* to override cache.
2419+
def __getitem__(self, key):
2420+
# Split into RGB tuple and opacity
2421+
# Matplotlib caches colors this way internally
2422+
rgb, alpha = key
2423+
if (
2424+
not isinstance(rgb, str) and np.iterable(rgb) and len(rgb) == 2
2425+
and isinstance(rgb[0], str) and isinstance(rgb[1], Number)
2426+
):
2427+
# Try to get the colormap
2428+
try:
2429+
cmap = _cmap_database[rgb[0]]
2430+
except (KeyError, TypeError):
2431+
pass
2432+
# Read the colormap value
2433+
else:
2434+
if isinstance(cmap, ListedColormap):
2435+
if not 0 <= rgb[1] < len(cmap.colors):
2436+
raise ValueError(
2437+
f'Color cycle sample for {rgb[0]!r} cycle must be '
2438+
f'between 0 and {len(cmap.colors) - 1}, got {rgb[1]}.'
2439+
)
2440+
rgb = cmap.colors[rgb[1]] # draw from list of colors
2441+
else:
2442+
if not 0 <= rgb[1] <= 1:
2443+
raise ValueError(
2444+
f'Colormap sample for {rgb[0]!r} colormap must be '
2445+
f'between 0 and 1, got {rgb[1]}.'
2446+
)
2447+
rgb = cmap(rgb[1]) # get color selection
2448+
return mcolors.to_rgba(rgb, alpha)
2449+
2450+
# Proceed as usual
2451+
return super().__getitem__((rgb, alpha))
2452+
2453+
24012454
class ColorDatabase(dict):
24022455
"""
24032456
Dictionary subclass used to replace the builtin matplotlib color
@@ -2448,46 +2501,24 @@ def cache(self):
24482501
return self._cache
24492502

24502503

2451-
class _ColorCache(dict):
2504+
def _init_cmap_database():
24522505
"""
2453-
Replacement for the native color cache.
2506+
Initialize the subclassed database.
24542507
"""
2455-
# Matplotlib 'color' args are passed to to_rgba, which tries to read
2456-
# directly from cache and if that fails, sanitizes input, which raises
2457-
# error on receiving (colormap, idx) tuple. So we *have* to override cache.
2458-
def __getitem__(self, key):
2459-
# Split into RGB tuple and opacity
2460-
# Matplotlib caches colors this way internally
2461-
rgb, alpha = key
2462-
if (
2463-
not isinstance(rgb, str) and np.iterable(rgb) and len(rgb) == 2
2464-
and isinstance(rgb[0], str) and isinstance(rgb[1], Number)
2465-
):
2466-
# Try to get the colormap
2467-
try:
2468-
cmap = _cmap_database[rgb[0]]
2469-
except (KeyError, TypeError):
2470-
pass
2471-
# Read the colormap value
2472-
else:
2473-
if isinstance(cmap, ListedColormap):
2474-
if not 0 <= rgb[1] < len(cmap.colors):
2475-
raise ValueError(
2476-
f'Color cycle sample for {rgb[0]!r} cycle must be '
2477-
f'between 0 and {len(cmap.colors) - 1}, got {rgb[1]}.'
2478-
)
2479-
rgb = cmap.colors[rgb[1]] # draw from list of colors
2480-
else:
2481-
if not 0 <= rgb[1] <= 1:
2482-
raise ValueError(
2483-
f'Colormap sample for {rgb[0]!r} colormap must be '
2484-
f'between 0 and 1, got {rgb[1]}.'
2485-
)
2486-
rgb = cmap(rgb[1]) # get color selection
2487-
return mcolors.to_rgba(rgb, alpha)
2488-
2489-
# Proceed as usual
2490-
return super().__getitem__((rgb, alpha))
2508+
# WARNING: Skip over the matplotlib native duplicate entries
2509+
# with suffixes '_r' and '_shifted'.
2510+
attr = '_cmap_registry' if hasattr(mcm, '_cmap_registry') else 'cmap_d'
2511+
database = getattr(mcm, attr)
2512+
if mcm.get_cmap is not _get_cmap:
2513+
mcm.get_cmap = _get_cmap
2514+
if not isinstance(database, ColormapDatabase):
2515+
database = {
2516+
key: value for key, value in database.items()
2517+
if key[-2:] != '_r' and key[-8:] != '_shifted'
2518+
}
2519+
database = ColormapDatabase(database)
2520+
setattr(mcm, attr, database)
2521+
return database
24912522

24922523

24932524
def _get_cmap(name=None, lut=None):
@@ -2687,24 +2718,6 @@ def _sanitize_key(self, key, mirror=True):
26872718
return key
26882719

26892720

2690-
# Replace color database with custom database
2691-
if not isinstance(mcolors._colors_full_map, ColorDatabase):
2692-
_map = ColorDatabase(mcolors._colors_full_map)
2693-
mcolors._colors_full_map = _map
2694-
mcolors.colorConverter.cache = _map.cache
2695-
mcolors.colorConverter.colors = _map
2696-
2697-
# Replace colormap database with custom database
2698-
# WARNING: Skip over the matplotlib native duplicate entries with
2699-
# suffixes '_r' and '_shifted'.
2700-
_cmap_database_attr = '_cmap_registry' if hasattr(mcm, '_cmap_registry') else 'cmap_d'
2701-
_cmap_database = getattr(mcm, _cmap_database_attr)
2702-
if mcm.get_cmap is not _get_cmap:
2703-
mcm.get_cmap = _get_cmap
2704-
if not isinstance(_cmap_database, ColormapDatabase):
2705-
_cmap_database = {
2706-
key: value for key, value in _cmap_database.items()
2707-
if key[-2:] != '_r' and key[-8:] != '_shifted'
2708-
}
2709-
_cmap_database = ColormapDatabase(_cmap_database)
2710-
setattr(mcm, _cmap_database_attr, _cmap_database)
2721+
# Initialize databases
2722+
_init_color_database()
2723+
_cmap_database = _init_cmap_database()

proplot/config.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,25 +1714,25 @@ def values(self):
17141714
yield self[key]
17151715

17161716

1717-
# Add custom font scalings to font_manager and monkey patch rcParams validator
1717+
# Initialize configuration
17181718
_init_user_file()
17191719
_init_user_folders()
1720+
1721+
# Patch matplotlib
17201722
_patch_colormaps()
17211723
_patch_validators()
17221724

17231725
# Register objects and configure settings
17241726
with timers._benchmark('cmaps'):
17251727
register_cmaps(default=True)
1726-
17271728
with timers._benchmark('cycles'):
17281729
register_cycles(default=True)
1729-
17301730
with timers._benchmark('colors'):
17311731
register_colors(default=True)
1732-
17331732
with timers._benchmark('fonts'):
17341733
register_fonts()
17351734

1735+
# Initialize configurator
17361736
with timers._benchmark('rc'):
17371737
_ = RcConfigurator()
17381738

0 commit comments

Comments
 (0)