Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4 colorscale updates #1647

Merged
merged 8 commits into from
Jul 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
135 changes: 84 additions & 51 deletions packages/python/plotly/_plotly_utils/basevalidators.py
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@ class ColorValidator(BaseValidator):
"red",
"rosybrown",
"royalblue",
"rebeccapurple",
"saddlebrown",
"salmon",
"sandybrown",
Expand Down Expand Up @@ -1503,86 +1504,118 @@ class ColorscaleValidator(BaseValidator):
},
"""

named_colorscales = [
"Greys",
"YlGnBu",
"Greens",
"YlOrRd",
"Bluered",
"RdBu",
"Reds",
"Blues",
"Picnic",
"Rainbow",
"Portland",
"Jet",
"Hot",
"Blackbody",
"Earth",
"Electric",
"Viridis",
"Cividis",
]

def __init__(self, plotly_name, parent_name, **kwargs):
super(ColorscaleValidator, self).__init__(
plotly_name=plotly_name, parent_name=parent_name, **kwargs
)

# named colorscales initialized on first use
self._named_colorscales = None

@property
def named_colorscales(self):
if self._named_colorscales is None:
import inspect
import itertools
from plotly import colors

colorscale_members = itertools.chain(
inspect.getmembers(colors.sequential),
inspect.getmembers(colors.diverging),
inspect.getmembers(colors.cyclical),
)

self._named_colorscales = {
c[0].lower(): c[1]
for c in colorscale_members
if isinstance(c, tuple)
and len(c) == 2
and isinstance(c[0], str)
and isinstance(c[1], list)
}

return self._named_colorscales

def description(self):
colorscales_str = "\n".join(
textwrap.wrap(
repr(sorted(list(self.named_colorscales))),
initial_indent=" " * 12,
subsequent_indent=" " * 13,
break_on_hyphens=False,
width=80,
)
)

desc = """\
The '{plotly_name}' property is a colorscale and may be
specified as:
- A list of colors that will be spaced evenly to create the colorscale.
Many predefined colorscale lists are included in the sequential, diverging,
and cyclical modules in the plotly.colors package.
- A list of 2-element lists where the first element is the
normalized color level value (starting at 0 and ending at 1),
and the second item is a valid color string.
(e.g. [[0, 'green'], [0.5, 'red'], [1.0, 'rgb(0, 0, 255)']])
- One of the following named colorscales:
['Greys', 'YlGnBu', 'Greens', 'YlOrRd', 'Bluered', 'RdBu',
'Reds', 'Blues', 'Picnic', 'Rainbow', 'Portland', 'Jet',
'Hot', 'Blackbody', 'Earth', 'Electric', 'Viridis', 'Cividis']
""".format(
plotly_name=self.plotly_name
{colorscales_str}
""".format(
plotly_name=self.plotly_name, colorscales_str=colorscales_str
)

return desc

def validate_coerce(self, v):
v_valid = False

if v is None:
# Pass None through
pass
if v is None:
v_valid = True
elif isinstance(v, string_types):
v_match = [
el
for el in ColorscaleValidator.named_colorscales
if el.lower() == v.lower()
]
if v_match:
v_lower = v.lower()
if v_lower in self.named_colorscales:
# Convert to color list
v = self.named_colorscales[v_lower]

# Convert to list of lists colorscale
d = len(v) - 1
v = [[(1.0 * i) / (1.0 * d), x] for i, x in enumerate(v)]

v_valid = True

elif is_array(v) and len(v) > 0:
invalid_els = [
e
for e in v
if (
not is_array(e)
or len(e) != 2
or not isinstance(e[0], numbers.Number)
or not (0 <= e[0] <= 1)
or not isinstance(e[1], string_types)
or ColorValidator.perform_validate_coerce(e[1]) is None
)
]
# If firset element is a string, treat as colorsequence
if isinstance(v[0], string_types):
invalid_els = [
e for e in v if ColorValidator.perform_validate_coerce(e) is None
]

if len(invalid_els) == 0:
v_valid = True

# Convert to list of lists colorscale
d = len(v) - 1
v = [[(1.0 * i) / (1.0 * d), x] for i, x in enumerate(v)]
else:
invalid_els = [
e
for e in v
if (
not is_array(e)
or len(e) != 2
or not isinstance(e[0], numbers.Number)
or not (0 <= e[0] <= 1)
or not isinstance(e[1], string_types)
or ColorValidator.perform_validate_coerce(e[1]) is None
)
]

if len(invalid_els) == 0:
v_valid = True
if len(invalid_els) == 0:
v_valid = True

# Convert to list of lists
v = [[e[0], ColorValidator.perform_validate_coerce(e[1])] for e in v]
# Convert to list of lists
v = [
[e[0], ColorValidator.perform_validate_coerce(e[1])] for e in v
]

if not v_valid:
self.raise_invalid_val(v)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
from numbers import Number
import six

from plotly import exceptions
from _plotly_utils import exceptions


# Built-in qualitative color sequences and sequential,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from .cmocean import balance, delta, curl # noqa: F401
from .carto import Armyrose, Fall, Geyser, Temps, Tealrose, Tropic, Earth # noqa: F401

from .plotlyjs import Picnic, Portland # noqa: F401

from ._swatches import _swatches

Expand Down
181 changes: 181 additions & 0 deletions packages/python/plotly/_plotly_utils/colors/plotlyjs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
# Copied from
# https://github.com/plotly/plotly.js/blob/master/src/components/colorscale/scales.js
_plotlyjs_scales = {
"Greys": [[0, "rgb(0,0,0)"], [1, "rgb(255,255,255)"]],
"YlGnBu": [
[0, "rgb(8,29,88)"],
[0.125, "rgb(37,52,148)"],
[0.25, "rgb(34,94,168)"],
[0.375, "rgb(29,145,192)"],
[0.5, "rgb(65,182,196)"],
[0.625, "rgb(127,205,187)"],
[0.75, "rgb(199,233,180)"],
[0.875, "rgb(237,248,217)"],
[1, "rgb(255,255,217)"],
],
"Greens": [
[0, "rgb(0,68,27)"],
[0.125, "rgb(0,109,44)"],
[0.25, "rgb(35,139,69)"],
[0.375, "rgb(65,171,93)"],
[0.5, "rgb(116,196,118)"],
[0.625, "rgb(161,217,155)"],
[0.75, "rgb(199,233,192)"],
[0.875, "rgb(229,245,224)"],
[1, "rgb(247,252,245)"],
],
"YlOrRd": [
[0, "rgb(128,0,38)"],
[0.125, "rgb(189,0,38)"],
[0.25, "rgb(227,26,28)"],
[0.375, "rgb(252,78,42)"],
[0.5, "rgb(253,141,60)"],
[0.625, "rgb(254,178,76)"],
[0.75, "rgb(254,217,118)"],
[0.875, "rgb(255,237,160)"],
[1, "rgb(255,255,204)"],
],
"Bluered": [[0, "rgb(0,0,255)"], [1, "rgb(255,0,0)"]],
# modified RdBu based on
# http:#www.kennethmoreland.com/color-maps/
"RdBu": [
[0, "rgb(5,10,172)"],
[0.35, "rgb(106,137,247)"],
[0.5, "rgb(190,190,190)"],
[0.6, "rgb(220,170,132)"],
[0.7, "rgb(230,145,90)"],
[1, "rgb(178,10,28)"],
],
# Scale for non-negative numeric values
"Reds": [
[0, "rgb(220,220,220)"],
[0.2, "rgb(245,195,157)"],
[0.4, "rgb(245,160,105)"],
[1, "rgb(178,10,28)"],
],
# Scale for non-positive numeric values
"Blues": [
[0, "rgb(5,10,172)"],
[0.35, "rgb(40,60,190)"],
[0.5, "rgb(70,100,245)"],
[0.6, "rgb(90,120,245)"],
[0.7, "rgb(106,137,247)"],
[1, "rgb(220,220,220)"],
],
"Picnic": [
[0, "rgb(0,0,255)"],
[0.1, "rgb(51,153,255)"],
[0.2, "rgb(102,204,255)"],
[0.3, "rgb(153,204,255)"],
[0.4, "rgb(204,204,255)"],
[0.5, "rgb(255,255,255)"],
[0.6, "rgb(255,204,255)"],
[0.7, "rgb(255,153,255)"],
[0.8, "rgb(255,102,204)"],
[0.9, "rgb(255,102,102)"],
[1, "rgb(255,0,0)"],
],
"Rainbow": [
[0, "rgb(150,0,90)"],
[0.125, "rgb(0,0,200)"],
[0.25, "rgb(0,25,255)"],
[0.375, "rgb(0,152,255)"],
[0.5, "rgb(44,255,150)"],
[0.625, "rgb(151,255,0)"],
[0.75, "rgb(255,234,0)"],
[0.875, "rgb(255,111,0)"],
[1, "rgb(255,0,0)"],
],
"Portland": [
[0, "rgb(12,51,131)"],
[0.25, "rgb(10,136,186)"],
[0.5, "rgb(242,211,56)"],
[0.75, "rgb(242,143,56)"],
[1, "rgb(217,30,30)"],
],
"Jet": [
[0, "rgb(0,0,131)"],
[0.125, "rgb(0,60,170)"],
[0.375, "rgb(5,255,255)"],
[0.625, "rgb(255,255,0)"],
[0.875, "rgb(250,0,0)"],
[1, "rgb(128,0,0)"],
],
"Hot": [
[0, "rgb(0,0,0)"],
[0.3, "rgb(230,0,0)"],
[0.6, "rgb(255,210,0)"],
[1, "rgb(255,255,255)"],
],
"Blackbody": [
[0, "rgb(0,0,0)"],
[0.2, "rgb(230,0,0)"],
[0.4, "rgb(230,210,0)"],
[0.7, "rgb(255,255,255)"],
[1, "rgb(160,200,255)"],
],
"Earth": [
[0, "rgb(0,0,130)"],
[0.1, "rgb(0,180,180)"],
[0.2, "rgb(40,210,40)"],
[0.4, "rgb(230,230,50)"],
[0.6, "rgb(120,70,20)"],
[1, "rgb(255,255,255)"],
],
"Electric": [
[0, "rgb(0,0,0)"],
[0.15, "rgb(30,0,100)"],
[0.4, "rgb(120,0,100)"],
[0.6, "rgb(160,90,0)"],
[0.8, "rgb(230,200,0)"],
[1, "rgb(255,250,220)"],
],
"Viridis": [
[0, "#440154"],
[0.06274509803921569, "#48186a"],
[0.12549019607843137, "#472d7b"],
[0.18823529411764706, "#424086"],
[0.25098039215686274, "#3b528b"],
[0.3137254901960784, "#33638d"],
[0.3764705882352941, "#2c728e"],
[0.4392156862745098, "#26828e"],
[0.5019607843137255, "#21918c"],
[0.5647058823529412, "#1fa088"],
[0.6274509803921569, "#28ae80"],
[0.6901960784313725, "#3fbc73"],
[0.7529411764705882, "#5ec962"],
[0.8156862745098039, "#84d44b"],
[0.8784313725490196, "#addc30"],
[0.9411764705882353, "#d8e219"],
[1, "#fde725"],
],
"Cividis": [
[0.000000, "rgb(0,32,76)"],
[0.058824, "rgb(0,42,102)"],
[0.117647, "rgb(0,52,110)"],
[0.176471, "rgb(39,63,108)"],
[0.235294, "rgb(60,74,107)"],
[0.294118, "rgb(76,85,107)"],
[0.352941, "rgb(91,95,109)"],
[0.411765, "rgb(104,106,112)"],
[0.470588, "rgb(117,117,117)"],
[0.529412, "rgb(131,129,120)"],
[0.588235, "rgb(146,140,120)"],
[0.647059, "rgb(161,152,118)"],
[0.705882, "rgb(176,165,114)"],
[0.764706, "rgb(192,177,109)"],
[0.823529, "rgb(209,191,102)"],
[0.882353, "rgb(225,204,92)"],
[0.941176, "rgb(243,219,79)"],
[1.000000, "rgb(255,233,69)"],
],
}

# Create variable named after each scale that contains the sequence of colors only
for scale_name, scale_pairs in _plotlyjs_scales.items():
scale_sequence = [c[1] for c in scale_pairs]
exec (
"{scale_name} = {scale_sequence}".format(
scale_name=scale_name, scale_sequence=scale_sequence
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def swatches():

swatches.__doc__ = _swatches.__doc__

Plotly = [
Plotly3 = [
"#0508b8",
"#1910d8",
"#3c19f0",
Expand Down Expand Up @@ -92,6 +92,8 @@ def swatches():
"#f0f921",
]

from .plotlyjs import Blackbody, Bluered, Electric, Hot, Jet, Rainbow # noqa: F401

from .colorbrewer import ( # noqa: F401
Blues,
BuGn,
Expand Down
Loading