Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
151 commits
Select commit Hold shift + click to select a range
0422fbb
Initial pull request
lukelbd Sep 18, 2019
baabc93
Merge pull request #55 from lukelbd/2dlatlon-bug
lukelbd Oct 21, 2019
dc48320
Construct base class skeletons and add folder search funcs
lukelbd Oct 22, 2019
8a4956e
Move config files and standardize searching locations
lukelbd Oct 24, 2019
8addbd0
Code quality changes
lukelbd Oct 24, 2019
b48f147
Cleanup, flesh out base classes
lukelbd Oct 25, 2019
a64a18e
Default transform bugfix
lukelbd Oct 25, 2019
473c489
Define wrappers on BasemapAxes for consistency with CartopyAxes
lukelbd Oct 25, 2019
9b720aa
Update docs regarding .proplotrc
lukelbd Oct 25, 2019
3bffca3
Update rcdocs
lukelbd Oct 25, 2019
4425813
Merge branch 'master' into custom-cmaps-cycles
lukelbd Oct 25, 2019
e9b2bea
Implement colormap modifying features on classes
lukelbd Oct 28, 2019
771dddb
Cleanup
lukelbd Oct 28, 2019
d6cd771
Revert to old config file/folder layout
lukelbd Oct 28, 2019
42ef8c2
Fill default ~/.proplotrc file with commented out lines
lukelbd Oct 28, 2019
f835850
Rename rc categories
lukelbd Oct 28, 2019
f11c283
Cleanup
lukelbd Oct 28, 2019
33e384c
Rename rc dicts again
lukelbd Oct 28, 2019
1203055
Rename Colormap.copy() --> from_cmap(), cleanup
lukelbd Oct 28, 2019
4b6d1a5
Bugfix
lukelbd Oct 28, 2019
47dd70f
Segmentdata bugs
lukelbd Oct 28, 2019
fab23de
Cleanup and standardize names
lukelbd Oct 29, 2019
5974268
Make concatenate + copy non-static, misc bugfixes
lukelbd Oct 29, 2019
fd420c6
Remove duplicate reverse features, more misc bugfixes
lukelbd Oct 29, 2019
ceb98fd
Various bugfixes (from testing colors.ipynb)
lukelbd Oct 29, 2019
683c6d7
Address codacy complaints
lukelbd Oct 29, 2019
49ef944
Update docs, fix save methods, add __repr__
lukelbd Oct 29, 2019
a4b9b6d
Fix save() bug, tweak __repr__()
lukelbd Oct 30, 2019
fd79457
Unused import
lukelbd Oct 30, 2019
31439dd
Merge pull request #57 from lukelbd/custom-cmaps-cycles
lukelbd Oct 30, 2019
0fe3bfc
Add new classes to __all__
lukelbd Oct 30, 2019
e1712e7
Repair save() docs
lukelbd Oct 30, 2019
f32e950
Fix merge conflict
lukelbd Oct 30, 2019
923f6b4
Cleanup save() extensions table
lukelbd Oct 30, 2019
704c7d3
Merge branch 'master' into dualax-factoryfunc-fixes
lukelbd Oct 30, 2019
629cf55
Typo in save() docs
lukelbd Oct 30, 2019
5ae9b22
Fix sphinx links
lukelbd Oct 30, 2019
5e61499
Plural classes
lukelbd Oct 30, 2019
26fae3b
Rename Colormap.copy --> Colormap.new, cleanup benchmarking code
lukelbd Oct 30, 2019
8984497
CmapDict docs
lukelbd Oct 30, 2019
894e454
ColorCacheDict docs
lukelbd Oct 30, 2019
89db9c0
ColorCacheDict docs
lukelbd Oct 30, 2019
200c2c9
Merge branch 'master' into dualax-factoryfunc-fixes
lukelbd Oct 30, 2019
774e7f8
Change back dualx/dualy syntax
lukelbd Oct 30, 2019
ee43c53
Fix bugs due to resetting scale at drawtime
lukelbd Oct 30, 2019
02bd8fe
Add back gridliner label warnings
lukelbd Oct 30, 2019
09ed143
Update notebooks
lukelbd Oct 30, 2019
f5eff48
Implement log/symlog formatter overrides on classes
lukelbd Oct 30, 2019
552a2a4
Merge pull request #52 from lukelbd/dualax-factoryfunc-fixes
lukelbd Oct 30, 2019
4a1247b
Use mixin _Scale class, better default dualx/y locators/formatters
lukelbd Oct 30, 2019
0ea6609
Dualx/y bugfix
lukelbd Oct 30, 2019
ef51e0f
Update cartesian axes examples
lukelbd Oct 31, 2019
a2708f6
Add ETA to README
lukelbd Oct 31, 2019
20a354c
Rename _Scale-->_ScaleBase
lukelbd Oct 31, 2019
633b0ad
Move notebooks folders
lukelbd Oct 31, 2019
53142b3
Colormap() converts input matplotlib cmaps to subclass
lukelbd Oct 31, 2019
170e51d
Remove commented out code from panels-to-parasites
lukelbd Oct 31, 2019
6e98b80
Fix CartopyAxes.text() bug
lukelbd Oct 31, 2019
b547de2
Fix lonlines bug
lukelbd Oct 31, 2019
d7430ba
Default cartopy transform bugfix
lukelbd Nov 1, 2019
9ce261b
Update geophysical data example
lukelbd Nov 1, 2019
1027fb3
Permit loading arbitrary colormap files
lukelbd Nov 6, 2019
86f35f1
Rename new() --> updated()
lukelbd Nov 11, 2019
b6fbd42
Merge branch 'master' into nbsphinx-docs
lukelbd Nov 13, 2019
56c945a
Restructure docs, add new pages
lukelbd Nov 13, 2019
f1f9c6f
Add git comments to why-proplot
lukelbd Nov 13, 2019
42d81f3
Why proplot section
lukelbd Nov 13, 2019
645ad8e
Why proplot
lukelbd Nov 15, 2019
4ca91e6
Various changes, fix Parameters tables
lukelbd Nov 16, 2019
20fb6f6
Update from stash
lukelbd Nov 16, 2019
010b1cc
Revert back to :parameters: so can list multiple params at once
lukelbd Nov 17, 2019
e285557
Add light theme stylesheet, remove unused rtd clone
lukelbd Nov 18, 2019
cda6963
Fix light theme sidebar
lukelbd Nov 18, 2019
a1e703b
Light mode final CSS edits
lukelbd Nov 18, 2019
b42fd81
Slightly darker background
lukelbd Nov 18, 2019
050e0eb
Make table colors grayscale
lukelbd Nov 18, 2019
63d1311
Contribute instructions
lukelbd Nov 18, 2019
20b4fdb
Lots of writing
lukelbd Nov 18, 2019
0e7940c
My hands are writing words
lukelbd Nov 18, 2019
d1ca33e
My hands are writing words
lukelbd Nov 18, 2019
67243e1
Initial commit of notebook files
lukelbd Nov 18, 2019
6749022
Use nbsphinx fork
lukelbd Nov 18, 2019
4a6e609
Set markdown cells to raw+RST, no more nbsphinx fork
lukelbd Nov 18, 2019
fc7747b
Travis CI
lukelbd Nov 18, 2019
45c6d5c
Link fixes, minor CSS changes, overview edits
lukelbd Nov 18, 2019
252244d
Parameter header edits
lukelbd Nov 18, 2019
d40a441
Add to quick overview, various other changes
lukelbd Nov 18, 2019
63cc63e
Links, better homepage, axistools cleanup
lukelbd Nov 19, 2019
43f7767
Quick overview and links cleanup
lukelbd Nov 19, 2019
5a53690
Split user guide notebooks into smaller sections
lukelbd Nov 19, 2019
c5e83a2
Contribution guide
lukelbd Nov 19, 2019
3288d58
proj.py docs
lukelbd Nov 19, 2019
c1f843a
API ref main page
lukelbd Nov 19, 2019
1a95106
Split up figure notebook sections
lukelbd Nov 19, 2019
4021238
Compare APIs in why-proplot, not user guide
lukelbd Nov 19, 2019
9c0781a
Split color usage notebook into 3 notebooks
lukelbd Nov 19, 2019
c12451c
Rename the axes classes
lukelbd Nov 19, 2019
c3a1aa5
Better admonition blocks, fix broken links
lukelbd Nov 19, 2019
120501c
Thinner tables, docs cleanup
lukelbd Nov 19, 2019
1060158
External links
lukelbd Nov 19, 2019
d0db1bf
Docs cleanup, add manifest, add INSTALL.rst
lukelbd Nov 20, 2019
0148841
Why proplot
lukelbd Nov 20, 2019
f28706f
Misc docs changes
lukelbd Nov 20, 2019
b270941
Fix notebook links, rename cmapline --> parametric
lukelbd Nov 20, 2019
cbb956b
Add parametric method to docs
lukelbd Nov 20, 2019
a1330ef
Fix wrapper docs links
lukelbd Nov 20, 2019
5459654
Fix sidebar colors for deeply nested entries
lukelbd Nov 20, 2019
33074ee
Figures notebook cleanup
lukelbd Nov 20, 2019
3015729
Tight layout notebook
lukelbd Nov 20, 2019
3554b57
Remove add-subplot workflow refs, fix sidebar colors/buttons
lukelbd Nov 20, 2019
7b49a86
Remove remaining add-subplot refs
lukelbd Nov 21, 2019
7b07b4a
subplots() docstring
lukelbd Nov 21, 2019
97d4ec7
Dark/light mode toggle (!), zerotrim bugfix
lukelbd Nov 24, 2019
0da79e3
API page changes
lukelbd Nov 24, 2019
a9673e5
Minor changes
lukelbd Nov 24, 2019
3f7f337
Stop documenting Circle() func
lukelbd Nov 24, 2019
4631ee7
Really fix zerotrim
lukelbd Nov 24, 2019
d3b0f0b
Faq, overview, fix links, align nbsphinx output
lukelbd Nov 24, 2019
f99fbdc
Dark/light mode toggles pygments stylesheet (!)
lukelbd Nov 24, 2019
c922439
Fix dark-light toggler
lukelbd Nov 24, 2019
bccf8d7
Use rubric:: for API page subheaders
lukelbd Nov 24, 2019
76c79e5
Style tweaks, misc changes
lukelbd Nov 24, 2019
ef7843e
Style tweaks, misc changes
lukelbd Nov 24, 2019
29ea57e
Use local pygment css files, cleanup, tweaks
lukelbd Nov 24, 2019
75ce94f
Test
lukelbd Nov 24, 2019
506c491
Larger fonts in examples, docs cleanup, custom_roles cleanup, misc bu…
lukelbd Nov 25, 2019
6b79f2f
Clean notebook output
lukelbd Nov 25, 2019
f47345d
Update contribution instructions
lukelbd Nov 25, 2019
98f9652
Fix merge conflict
lukelbd Nov 25, 2019
d6a7c5a
Stylesheet bugfixes
lukelbd Nov 25, 2019
fb64eb0
Overview, faq, why proplot
lukelbd Nov 25, 2019
8bbe050
Remove units section
lukelbd Nov 25, 2019
efb4475
Why proplot
lukelbd Nov 25, 2019
e43db85
Why proplot
lukelbd Nov 25, 2019
cebc74e
Why proplot
lukelbd Nov 25, 2019
62d94e0
Codacy complaints
lukelbd Nov 25, 2019
2c1e3e1
Why and overview
lukelbd Nov 25, 2019
6736ea6
Overview and why-proplot, split nb_setup() into 3 funcs
lukelbd Nov 26, 2019
e9e8634
Why proplot
lukelbd Nov 26, 2019
53aff70
Code qaulity, Colormap.from_list improvements, cyclic + transparent m…
lukelbd Nov 27, 2019
b08e52d
Merge branch 'master' into nbsphinx-docs
lukelbd Nov 27, 2019
1f4ba46
Physical units descrip
lukelbd Nov 27, 2019
f1d2e9d
Physical units
lukelbd Nov 27, 2019
0d5127e
Remove 'default' formatter, code quality fixes
lukelbd Nov 27, 2019
acffc34
Use setuptools_scm, no more hardcoded version / MANIFEST
lukelbd Nov 27, 2019
8743b85
Travis fix (just notebooks for now)
lukelbd Nov 27, 2019
b49f54f
Fix sphinx-build requirements
lukelbd Nov 27, 2019
ab0ca7e
Use conda for documentation build reqs
lukelbd Nov 27, 2019
c7dbcae
Fix conda activate
lukelbd Nov 27, 2019
d34d888
Fix proplot not found issue
lukelbd Nov 27, 2019
0c6d581
Bugfix (travis caught it! awesome!)
lukelbd Nov 27, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Remove duplicate reverse features, more misc bugfixes
  • Loading branch information
lukelbd committed Oct 29, 2019
commit fd420c66b4f6ebc91db35368b0eb59958932a45e
151 changes: 59 additions & 92 deletions proplot/styletools.py
Original file line number Diff line number Diff line change
Expand Up @@ -417,14 +417,12 @@ def _clip_colors(colors, clip=True, gray=0.2):
# warnings.warn(f'{message} "{name}" channel ( > 1).')
return colors

def _make_segmentdata_array(values, ratios=None, reverse=False, **kwargs):
def _make_segmentdata_array(values, ratios=None, **kwargs):
"""Constructs a list of linear segments for an individual channel.
This was made so that user can input e.g. a callable function for
one channel, but request linear interpolation for another one."""
# Allow callables
if callable(values):
if reverse:
values = lambda x: values(1-x)
return values # just return the callable
values = np.atleast_1d(values)
if len(values) == 1:
Expand All @@ -445,12 +443,11 @@ def _make_segmentdata_array(values, ratios=None, reverse=False, **kwargs):

# Build vector
array = []
slicer = slice(None,None,-1) if reverse else slice(None)
for x,value in zip(xvals,values[slicer]):
for x,value in zip(xvals,values):
array.append((x, value, value))
return array

def make_mapping_array(N, data, gamma=1.0, reverse=False):
def make_mapping_array(N, data, gamma=1.0, inverse=False):
r"""
Mostly a copy of `~matplotlib.colors.makeMappingArray`, but allows
*circular* hue gradations along 0-360, disables clipping of
Expand Down Expand Up @@ -478,7 +475,7 @@ def make_mapping_array(N, data, gamma=1.0, reverse=False):
:math:`w_i` ranges from 0 to 1 between rows ``i`` and ``i+1``.
If `gamma` is float, it applies to every transition. Otherwise,
its length must equal ``data.shape[0]-1``.
reverse : bool, optional
inverse : bool, optional
If ``True``, :math:`w_i^{\gamma_i}` is replaced with
:math:`1 - (1 - w_i)^{\gamma_i}` -- that is, when `gamma` is greater
than 1, this weights colors toward *higher* channel values instead
Expand Down Expand Up @@ -539,7 +536,7 @@ def make_mapping_array(N, data, gamma=1.0, reverse=False):
ireverse = False
if ci > 1: # i.e. more than 1 color in this 'segment'
ireverse = ((y0[ind[ui]] - y1[ind[ui]-1]) < 0) # by default want to weight toward a *lower* channel value
if reverse:
if inverse:
ireverse = (not ireverse)
if ireverse:
distance[ui:ui + ci] = 1 - (1 - distance[ui:ui + ci])**gamma
Expand Down Expand Up @@ -683,16 +680,13 @@ def concatenate(self, *args, ratios=1, name=None, **kwargs):
"""
# Try making a simple copy
if not args:
if kwargs:
return self.copy(**kwargs)
else:
return self
raise ValueError(f'Got zero positional args, you must provide at least one.')
if not all(type(cmap) is type(self) for cmap in args):
raise ValueError(f'Colormaps {cmap.name + ": " + repr(cmap) for cmap in args} must all belong to the same class.')
cmaps = (self, *args)
spaces = {getattr(cmap, '_space', None) for cmap in args}
if len(spaces) > 1:
raise ValueError(f'Cannot merge colormaps in the different HSL spaces {repr(spaces)}.')
spaces = {cmap.name: getattr(cmap, '_space', None) for cmap in cmaps}
if len({*spaces.values(),}) > 1:
raise ValueError(f'Cannot merge PerceptuallyUniformColormaps that use different colorspaces: {repr(spaces)}.')
N = kwargs.pop('N', None)
N = N or len(cmaps) * rcParams['image.lut']
if name is None:
Expand Down Expand Up @@ -1007,15 +1001,13 @@ def concatenate(self, *args, name=None, N=None, **kwargs):
the number of colors in the concatenated lists.
"""
if not args:
if kwargs:
return self.copy(**kwargs)
else:
return self
if not all(isinstance(cmap, ListedColormap) for cmap in args):
raise ValueError(f'Got zero positional args, you must provide at least one.')
if not all(type(cmap) is type(self) for cmap in args):
raise ValueError(f'Input arguments {args} must all be ListedColormap.')
cmaps = (self, *args)
if name is None:
name = '_'.join(cmap.name for cmap in args)
colors = [color for cmap in args for color in cmap.colors]
name = '_'.join(cmap.name for cmap in cmaps)
colors = [color for cmap in cmaps for color in cmap.colors]
return self.copy(colors, name, N or len(colors))

def save(self, path=None):
Expand Down Expand Up @@ -1169,11 +1161,11 @@ def _init(self):
each value in the lookup table from 'input' to RGB."""
# First generate the lookup table
channels = ('hue','saturation','luminance')
reverse = (False, False, True) # gamma weights *low chroma* and *high luminance*
inverses = (False, False, True) # gamma weights *low chroma* and *high luminance*
gammas = (1.0, self._gamma1, self._gamma2)
self._lut_hsl = np.ones((self.N+3, 4), float) # fill
for i,(channel,gamma,reverse) in enumerate(zip(channels,gammas,reverse)):
self._lut_hsl[:-3,i] = make_mapping_array(self.N, self._segmentdata[channel], gamma, reverse)
for i,(channel,gamma,inverse) in enumerate(zip(channels,gammas,inverses)):
self._lut_hsl[:-3,i] = make_mapping_array(self.N, self._segmentdata[channel], gamma, inverse)
if 'alpha' in self._segmentdata:
self._lut_hsl[:-3,3] = make_mapping_array(self.N, self._segmentdata['alpha'])
self._lut_hsl[:-3,0] %= 360
Expand Down Expand Up @@ -1226,9 +1218,7 @@ def copy(self, name=None, segmentdata=None, N=None, space=None,
cyclic=cyclic)

@staticmethod
def from_color(name, color,
fade=100, reverse=False, space='hsl',
**kwargs):
def from_color(name, color, fade=100, space='hsl', **kwargs):
"""
Returns a monochromatic "sequential" colormap that blends from white
or near-white to the input color.
Expand All @@ -1247,33 +1237,26 @@ def from_color(name, color,
If RGB tuple, hex string, or named color string, the luminance and
saturation (but *not* the hue) from this color are used for the
left-hand side of the colormap.
reverse : bool, optional
Whether to reverse the colormap.
space : {'hcl', 'hsl', 'hpl'}, optional
Colorspace in which the luminance is varied.
The colorspace in which the luminance is varied.

Other parameters
----------------
**kwargs
Passed to `PerceptuallyUniformColormap.from_hsl`.
"""
# Get colorspace and channel values
h, s, l = to_xyz(to_rgb(color), space)
if isinstance(fade, Number):
fs, fl = s, fade
else:
_, fs, fl = to_xyz(to_rgb(fade), space)
# Build colormap
if reverse:
s, l = (s,fs), (l,fl) # from color to faded
else:
s, l = (fs,s), (fl,l) # from faded to color
return PerceptuallyUniformColormap.from_hsl(name, h, s, l, space=space, **kwargs)
return PerceptuallyUniformColormap.from_hsl(name,
h, (fs,s), (fl,l), space=space, **kwargs)

@staticmethod
def from_hsl(name,
hue=0, saturation=100, luminance=(100, 20), alpha=None,
ratios=None, reverse=False, **kwargs):
ratios=None, **kwargs):
"""
Makes a `~PerceptuallyUniformColormap` by specifying the hue,
saturation, and luminance transitions individually.
Expand All @@ -1292,12 +1275,9 @@ def from_hsl(name,
value for that color is looked up.

If scalar, the hue does not change across the colormap.
saturation : float, str, or list thereof, optional
As with `hue`, but for the saturation channel.
luminance : float, str, or list thereof, optional
As with `hue`, but for the luminance channel.
alpha : float, str, or list thereof, optional
As with `hue`, but for the alpha channel (the opacity).
saturation, luminance, alpha : float, str, or list thereof, optional
As with `hue`, but for the saturation, luminance, and alpha
(opacity) channels, respectively.
ratios : list of float, optional
Relative extent of the transitions indicated by the channel
value lists.
Expand All @@ -1306,23 +1286,23 @@ def from_hsl(name,
places the *x*-coordinate where the luminance is 50 at 0.66 --
the white to gray transition is "slower" than the gray to black
transition.
reverse : bool, optional
Whether to reverse the final colormap.

Other parameters
----------------
**kwargs
Passed to `PerceptuallyUniformColormap`.
"""
# Build dictionary, easy peasy
cdict = {}
alpha = _notNone(alpha, 1.0)
for key,channel in zip(('hue','saturation','luminance','alpha'), (hue,saturation,luminance,alpha)):
cdict[key] = _make_segmentdata_array(channel, ratios, reverse, **kwargs)
for key,channel in zip(
('hue','saturation','luminance','alpha'),
(hue,saturation,luminance,alpha)
):
cdict[key] = _make_segmentdata_array(channel, ratios, **kwargs)
return PerceptuallyUniformColormap(name, cdict, **kwargs)

@staticmethod
def from_list(name, colors, ratios=None, reverse=False, **kwargs):
def from_list(name, colors, ratios=None, **kwargs):
"""
Makes a `PerceptuallyUniformColormap` from a list of RGB colors.

Expand All @@ -1336,8 +1316,6 @@ def from_list(name, colors, ratios=None, reverse=False, **kwargs):
Length ``len(colors)-1`` list of scales for *x*-coordinate
transitions between colors. Bigger numbers indicate a slower
transition, smaller numbers indicate a faster transition.
reverse : bool, optional
Whether to reverse the result.

Other parameters
----------------
Expand All @@ -1359,7 +1337,7 @@ def from_list(name, colors, ratios=None, reverse=False, **kwargs):
cdict['alpha'] = lambda x: 1.0 # dummy function that always returns 1.0
# Build data arrays
for key,channel in zip(keys,channels):
cdict[key] = _make_segmentdata_array(channel, ratios, reverse, **kwargs)
cdict[key] = _make_segmentdata_array(channel, ratios, **kwargs)
return PerceptuallyUniformColormap(name, cdict, **kwargs)

@docstring.dedent_interpd
Expand Down Expand Up @@ -1387,13 +1365,13 @@ class CmapDict(dict):
Behaves like a dictionary, with three new features:

1. Names are case insensitive: ``'Blues'``, ``'blues'``, and ``'bLuEs'``
are all valid names for the "Blues" colormap.
are all valid names for the "Blues" colormap.
2. "Reversed" colormaps are not stored directly: Requesting e.g.
``'Blues_r'`` will just look up ``'Blues'``, then return the result
of the `~matplotlib.colors.Colormap.reversed` method.
``'Blues_r'`` will just look up ``'Blues'``, then return the result
of the `~matplotlib.colors.Colormap.reversed` method.
3. Diverging colormap names can be referenced by their "inverse" name.
For example, ``'BuRd'`` is equivalent to ``'RdBu_r'``, as are
``'BuYlRd'`` and ``'RdYlBu_r'``.
For example, ``'BuRd'`` is equivalent to ``'RdBu_r'``, as are
``'BuYlRd'`` and ``'RdYlBu_r'``.
"""
def __init__(self, kwargs):
"""
Expand Down Expand Up @@ -1647,55 +1625,50 @@ def Colormap(*args, name=None, listmode='perceptual',
"""
# Initial stuff
if not args:
raise ValueError(f'Colormap requires at least one positional argument.')
raise ValueError(f'Colormap() requires at least one positional argument.')
if listmode not in ('listed', 'linear', 'perceptual'):
raise ValueError(f'Invalid listmode={listmode!r}. Options are "listed", "linear", and "perceptual".')
cmaps = []
name_tmp = '_no_name' # name required, but we only care about name of final merged map
for i,cmap in enumerate(args):
if isinstance(cmap,str):
try:
cmap = mcm.cmap_d[cmap]
except KeyError:
pass
# Properties specific to each map
ireverse = False if not np.iterable(reverse) else reverse[i]
ileft = None if not np.iterable(left) else left[i]
iright = None if not np.iterable(right) else right[i]
# Interpret existing colormap
if isinstance(cmap, mcolors.Colormap):
pass
# Dictionary of hue/sat/luminance values or 2-tuples representing linear transition
elif isinstance(cmap, dict):
try:
cmap = PerceptuallyUniformColormap.from_hsl('_no_name', **cmap)
except TypeError:
raise ValueError(f'Invalid input "{cmap}" for from_hsl method.')
cmap = PerceptuallyUniformColormap.from_hsl(name_tmp, **cmap)
# List of color tuples or color strings, i.e. iterable of iterables
elif not isinstance(cmap, str) and np.iterable(cmap) and all(np.iterable(color) for color in cmap):
cmap = [to_rgb(color, cycle=cycle) for color in cmap] # transform C0, C1, etc. to actual names
if listmode == 'listed':
cmap = ListedColormap(cmap, '_no_name')
cmap = ListedColormap(cmap, name_tmp)
elif listmode == 'linear':
cmap = LinearSegmentedColormap.from_list('_no_name', cmap)
cmap = LinearSegmentedColormap.from_list(name_tmp, cmap)
else:
cmap = PerceptuallyUniformColormap.from_list('_no_name', cmap)
cmap = PerceptuallyUniformColormap.from_list(name_tmp, cmap)
# Monochrome colormap from input color
else:
ireverse = False
if isinstance(cmap, str) and cmap[-2:] == '_r':
cmap = cmap[:-2]
ireverse = True
cmap, ireverse = cmap[:-2], (not ireverse)
try:
color = to_rgb(cmap, cycle=cycle)
except (ValueError, TypeError):
if not isinstance(cmap, str):
raise ValueError(f'Invalid cmap, cycle, or color "{cmap}".')
else:
raise ValueError(f'Invalid cmap, cycle, or color "{cmap}".\n'
f'Valid cmap and cycle names: {", ".join(sorted(mcm.cmap_d))}.\n'
f'Valid color names: {", ".join(sorted(mcolors.colorConverter.colors.keys()))}.')
cmap = PerceptuallyUniformColormap.from_color('_no_name',
color, fade=fade, reverse=ireverse)
msg = f'Invalid cmap, cycle, or color "{cmap}".'
if isinstance(cmap, str):
msg += (f'\nValid cmap and cycle names: {", ".join(sorted(mcm.cmap_d))}.'
f'\nValid color names: {", ".join(sorted(mcolors.colorConverter.colors.keys()))}.')
raise ValueError(msg)
cmap = PerceptuallyUniformColormap.from_color(name_tmp, color, fade)
# Transform colormap by clipping colors or reversing
ireverse = False if not np.iterable(reverse) else reverse[i]
ileft = None if not np.iterable(left) else left[i]
iright = None if not np.iterable(right) else right[i]
if ileft is not None or iright is not None:
cmap = cmap.sliced(ileft, iright)
if ireverse:
Expand All @@ -1704,26 +1677,20 @@ def Colormap(*args, name=None, listmode='perceptual',

# Now merge the result of this arbitrary user input
# Since we are merging cmaps, potentially *many* color transitions; use big number by default
if len(cmaps) > 1: # much more common
cls = None
for icls in (ListedColormap, LinearSegmentedColormap):
if all(isinstance(cmap,icls) for cmap in cmaps):
cls = icls
if cls is None:
raise ValueError(f'Colormaps {cmap.name + ": " + repr(cmap) for cmap in cmaps} must all belong to the same class.')
cmap = cls.concatenate(*cmaps, **kwargs)
if len(cmaps) > 1: # more than one map?
cmaps[0].concatenate(*cmaps[1:], **kwargs)
elif kwargs: # modify any props?
cmaps[0].copy(**kwargs)

# Cut the edges or center
left = None if np.iterable(left) else left
right = None if np.iterable(right) else right
if left is not None or right is not None or cut is not None:
cmap = cmap.sliced(left, right, cut=cut, name=name)
cmap = cmap.sliced(left, right, cut=cut)

# Rotate the colormap
if shift: # i.e. is non-zero
cmap = cmap.shifted(shift, name=name)
cmap = cmap.shifted(shift)

# Reverse colormap
if not np.iterable(reverse) and reverse:
Expand All @@ -1735,7 +1702,7 @@ def Colormap(*args, name=None, listmode='perceptual',

# Register and save the colormap
if name is None:
name = cmap.name # may have been modified
name = cmap.name # may have been modified by various methods, e.g. shited() and reversed()
else:
cmap.name = name
mcm.cmap_d[name] = cmap
Expand Down