@@ -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+
24012454class 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
24932524def _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 ()
0 commit comments