@@ -1096,16 +1096,19 @@ def shifted(self, shift=None, name=None, **kwargs):
1096
1096
the original colormap is returned.
1097
1097
name : str, optional
1098
1098
The name of the new colormap. Default is
1099
- ``self.name + '_shifted'``.
1099
+ ``self.name + '_s'``.
1100
+
1101
+ Other parameters
1102
+ ----------------
1100
1103
**kwargs
1101
- Passed to `LinearSegmentedColormap.updated `
1102
- or `PerceptuallyUniformColormap.updated `.
1104
+ Passed to `LinearSegmentedColormap.copy `
1105
+ or `PerceptuallyUniformColormap.copy `.
1103
1106
"""
1104
1107
shift = ((shift or 0 ) / 360 ) % 1
1105
1108
if shift == 0 :
1106
1109
return self
1107
1110
if name is None :
1108
- name = self .name + '_shifted '
1111
+ name = self .name + '_s '
1109
1112
if not self ._cyclic :
1110
1113
_warn_proplot (
1111
1114
f'Shifting non-cyclic colormap { self .name !r} . '
@@ -1413,12 +1416,12 @@ def shifted(self, shift=None, name=None):
1413
1416
The number of places to shift, between ``-self.N`` and ``self.N``.
1414
1417
If ``None``, the original colormap is returned.
1415
1418
name : str, optional
1416
- The new colormap name. Default is ``self.name + '_shifted '``.
1419
+ The new colormap name. Default is ``self.name + '_s '``.
1417
1420
"""
1418
1421
if not shift :
1419
1422
return self
1420
1423
if name is None :
1421
- name = self .name + '_shifted '
1424
+ name = self .name + '_s '
1422
1425
shift = shift % len (self .colors )
1423
1426
colors = [* self .colors ] # ensure list
1424
1427
colors = colors [shift :] + colors [:shift ]
@@ -1847,7 +1850,9 @@ class CmapDict(dict):
1847
1850
"""
1848
1851
Dictionary subclass used to replace the `matplotlib.cm.cmap_d`
1849
1852
colormap dictionary. See `~CmapDict.__getitem__` and
1850
- `~CmapDict.__setitem__` for details.
1853
+ `~CmapDict.__setitem__` for details. This class also handles the
1854
+ `colormaps` and `cycles` variables, meant to provide users with an
1855
+ easily accessible list of all registered colormap and cycle names.
1851
1856
"""
1852
1857
def __init__ (self , kwargs ):
1853
1858
"""
@@ -1857,28 +1862,16 @@ def __init__(self, kwargs):
1857
1862
The source dictionary.
1858
1863
"""
1859
1864
for key , value in kwargs .items ():
1860
- if not isinstance (key , str ):
1861
- raise KeyError (f'Invalid key { key } . Must be string.' )
1862
1865
self .__setitem__ (key , value , sort = False )
1863
- try :
1864
- for record in (cmaps , cycles ):
1865
- record [:] = sorted (record )
1866
- except NameError :
1867
- pass
1866
+ self ._record_update (kwargs , sort = True )
1868
1867
1869
1868
def __delitem__ (self , key ):
1870
1869
"""
1871
1870
Delete the item from the list records.
1872
1871
"""
1872
+ key = self ._sanitize_key (key )
1873
+ self ._record_delete (key )
1873
1874
super ().__delitem__ (self , key )
1874
- try :
1875
- for record in (cmaps , cycles ):
1876
- try :
1877
- record .remove (key )
1878
- except ValueError :
1879
- pass
1880
- except NameError :
1881
- pass
1882
1875
1883
1876
def __getitem__ (self , key ):
1884
1877
"""
@@ -1887,16 +1880,16 @@ def __getitem__(self, key):
1887
1880
1888
1881
* If the key ends in ``'_r'``, the result of ``cmap.reversed()`` is
1889
1882
returned for the colormap registered under the name ``key[:-2]``.
1890
- * If it ends in ``'_shifted '``, the result of ``cmap.shifted(180)`` is
1883
+ * If it ends in ``'_s '``, the result of ``cmap.shifted(180)`` is
1891
1884
returned for the colormap registered under the name ``cmap[:-8]``.
1892
1885
* Reversed diverging colormaps can be requested with their "reversed"
1893
1886
name -- for example, ``'BuRd'`` is equivalent to ``'RdBu_r'``.
1894
1887
"""
1895
1888
key = self ._sanitize_key (key , mirror = True )
1896
- shift = ( key [- 8 :] == '_shifted' )
1889
+ shift = key [- 2 :] == '_s'
1897
1890
if shift :
1898
- key = key [:- 8 ]
1899
- reverse = ( key [- 2 :] == '_r' )
1891
+ key = key [:- 2 ]
1892
+ reverse = key [- 2 :] == '_r'
1900
1893
if reverse :
1901
1894
key = key [:- 2 ]
1902
1895
value = super ().__getitem__ (key ) # may raise keyerror
@@ -1925,31 +1918,27 @@ def __setitem__(self, key, item, sort=True):
1925
1918
`~matplotlib.colors.LinearSegmentedColormap`, it is converted to the
1926
1919
ProPlot `ListedColormap` or `LinearSegmentedColormap` subclass.
1927
1920
"""
1921
+ if not isinstance (key , str ):
1922
+ raise KeyError (f'Invalid key { key !r} . Must be string.' )
1928
1923
if isinstance (item , (ListedColormap , LinearSegmentedColormap )):
1929
1924
pass
1930
1925
elif isinstance (item , mcolors .LinearSegmentedColormap ):
1931
1926
item = LinearSegmentedColormap (
1932
- item .name , item ._segmentdata , item .N , item ._gamma )
1927
+ item .name , item ._segmentdata , item .N , item ._gamma
1928
+ )
1933
1929
elif isinstance (item , mcolors .ListedColormap ):
1934
1930
item = ListedColormap (
1935
- item .colors , item .name , item .N )
1936
- elif item is None :
1937
- return
1931
+ item .colors , item .name , item .N
1932
+ )
1938
1933
else :
1939
1934
raise ValueError (
1940
1935
f'Invalid colormap { item } . Must be instance of '
1941
1936
'matplotlib.colors.ListedColormap or '
1942
1937
'matplotlib.colors.LinearSegmentedColormap.'
1943
1938
)
1944
1939
key = self ._sanitize_key (key , mirror = False )
1945
- try :
1946
- record = cycles if isinstance (item , ListedColormap ) else cmaps
1947
- record .append (key )
1948
- if sort :
1949
- record [:] = sorted (record )
1950
- except NameError :
1951
- pass
1952
- return super ().__setitem__ (key , item )
1940
+ self ._record_update ({key : item }, sort = sort )
1941
+ super ().__setitem__ (key , item )
1953
1942
1954
1943
def __contains__ (self , item ):
1955
1944
"""
@@ -1961,17 +1950,51 @@ def __contains__(self, item):
1961
1950
except KeyError :
1962
1951
return False
1963
1952
1953
+ @staticmethod
1954
+ def _record_delete (key ):
1955
+ """
1956
+ Remove the `colormaps` or `cycles` record.
1957
+ """
1958
+ try :
1959
+ records = (cmaps , cycles )
1960
+ except NameError :
1961
+ pass
1962
+ else :
1963
+ for record in records :
1964
+ try :
1965
+ record .remove (key )
1966
+ except ValueError :
1967
+ pass
1968
+
1969
+ @staticmethod
1970
+ def _record_update (kwargs , sort = False ):
1971
+ """
1972
+ Update the `colormaps` or `cycles` record.
1973
+ """
1974
+ record = None
1975
+ try :
1976
+ cmaps , cycles
1977
+ except NameError :
1978
+ pass
1979
+ else :
1980
+ for key , item in kwargs .items ():
1981
+ record = cycles if isinstance (item , ListedColormap ) else cmaps
1982
+ record .append (key )
1983
+ if sort :
1984
+ record [:] = sorted (record )
1985
+
1964
1986
def _sanitize_key (self , key , mirror = True ):
1965
1987
"""
1966
- Return the sanitized colormap name.
1988
+ Return the sanitized colormap name. This is used for lookups *and*
1989
+ assignments.
1967
1990
"""
1968
1991
if not isinstance (key , str ):
1969
1992
raise KeyError (f'Invalid key { key !r} . Key must be a string.' )
1970
1993
key = key .lower ()
1971
- reverse = False
1972
- if key [- 2 :] == '_r' :
1994
+ key = re .sub (r'\A(grays)(?:_r|_s)?\Z' , 'greys' , key )
1995
+ reverse = key [- 2 :] == '_r'
1996
+ if reverse :
1973
1997
key = key [:- 2 ]
1974
- reverse = True
1975
1998
if mirror and not super ().__contains__ (key ): # search for mirrored key
1976
1999
key_mirror = key
1977
2000
for pair in CMAPS_DIVERGING :
@@ -1981,47 +2004,12 @@ def _sanitize_key(self, key, mirror=True):
1981
2004
except (ValueError , KeyError ):
1982
2005
continue
1983
2006
if super ().__contains__ (key_mirror ):
1984
- reverse = ( not reverse )
2007
+ reverse = not reverse
1985
2008
key = key_mirror
1986
2009
if reverse :
1987
2010
key = key + '_r'
1988
2011
return key
1989
2012
1990
- def get (self , key , * args ):
1991
- """
1992
- Retrieve the sanitized colormap name.
1993
- """
1994
- key = self ._sanitize_key (key , mirror = True )
1995
- return super ().get (key , * args )
1996
-
1997
- def pop (self , key , * args ):
1998
- """
1999
- Pop the sanitized colormap name.
2000
- """
2001
- key = self ._sanitize_key (key , mirror = True )
2002
- try :
2003
- for record in (cmaps , cycles ):
2004
- try :
2005
- record .remove (key )
2006
- except ValueError :
2007
- pass
2008
- except NameError :
2009
- pass
2010
- return super ().pop (key , * args )
2011
-
2012
- def update (self , * args , ** kwargs ):
2013
- """
2014
- Update the dictionary with sanitized colormap names.
2015
- """
2016
- if len (args ) == 1 :
2017
- kwargs .update (args [0 ])
2018
- elif len (args ) > 1 :
2019
- raise TypeError (
2020
- f'update() expected at most 1 arguments, got { len (args )} .'
2021
- )
2022
- for key , value in kwargs .items ():
2023
- self [key ] = value
2024
-
2025
2013
2026
2014
class _ColorMappingOverride (mcolors ._ColorMapping ):
2027
2015
"""
@@ -2041,16 +2029,15 @@ class ColorDict(dict):
2041
2029
"""
2042
2030
def __getitem__ (self , key ):
2043
2031
"""
2044
- Allows user to select colors from arbitrary named colormaps and
2045
- color cycles.
2032
+ Permit selections from arbitrary named colormaps and color cycles:
2046
2033
2047
2034
* For a smooth colormap, usage is e.g. ``color=('Blues', 0.8)``. The
2048
2035
number is the colormap index, and must be between 0 and 1.
2049
2036
* For a color cycle, usage is e.g. ``color=('colorblind', 2)``. The
2050
2037
number is the list index.
2051
2038
2052
- These examples work with any
2053
- matplotlib command that accepts a `color` keyword arg.
2039
+ These examples work with any matplotlib command that accepts a `color`
2040
+ keyword arg.
2054
2041
"""
2055
2042
# Matplotlib 'color' args are passed to to_rgba, which tries to read
2056
2043
# directly from cache and if that fails, sanitizes input, which
@@ -2071,16 +2058,14 @@ def __getitem__(self, key):
2071
2058
f'between 0 and { len (cmap .colors )- 1 } , '
2072
2059
f'got { rgb [1 ]} .'
2073
2060
)
2074
- # draw color from the list of colors, using index
2075
- rgb = cmap .colors [rgb [1 ]]
2061
+ rgb = cmap .colors [rgb [1 ]] # draw from list of colors
2076
2062
else :
2077
2063
if not 0 <= rgb [1 ] <= 1 :
2078
2064
raise ValueError (
2079
2065
f'Colormap sample for { rgb [0 ]!r} colormap must be '
2080
2066
f'between 0 and 1, got { rgb [1 ]} .'
2081
2067
)
2082
- # interpolate color from colormap, using key in range 0-1
2083
- rgb = cmap (rgb [1 ])
2068
+ rgb = cmap (rgb [1 ]) # get color selection
2084
2069
rgba = mcolors .to_rgba (rgb , alpha )
2085
2070
return rgba
2086
2071
return super ().__getitem__ ((rgb , alpha ))
0 commit comments