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

Add 256-color palettes, add a function to generate diverging palettes #9241

Closed
russellburdt opened this issue Sep 25, 2019 · 22 comments

Comments

@russellburdt
Copy link
Contributor

@russellburdt russellburdt commented Sep 25, 2019

This feature request will modify the bokeh.palettes module to include additional 256-color palettes and a diverging_palette function.

The problem this feature request could be considered to solve is that bokeh 1.3.4 palettes do not currently replicate all of the available matplotlib 3.1.1 palettes.

Color palettes in bokeh are hard-coded as lists of hex color strings. For example,

>>> from bokeh import palettes
>>> palettes.Reds9
['#67000d', '#a50f15', '#cb181d', '#ef3b2c', '#fb6a4a', '#fc9272', '#fcbba1', '#fee0d2', '#fff5f0']

Max size of a palettes.Reds palette in bokeh is 9 which may hide information in a chart where colors encode numbers. A 256-color palette could encode more information.

reds

This feature request will add several 256-color palettes (including but not limited to):

palettes256

A second component of this feature request is to add a function to the bokeh.palettes module that can return any diverging palette created as a piecewise linear interpolation of fixed palettes.

diverging1

The diverging_palette function will also support asymmetric diverging palettes, which means the intersection of the two palettes constituting the diverging palette is somewhere other than the middle. This can be useful to create charts where high and low values are mapped to colors asymmetrically (e.g. as in this blog post).

diverging2

The diverging_palette function can be implemented as in the code below. It is a direct manipulation of input palettes that uses the already-implemented linear_palette function. A ValueError will be raised by the linear_palette function if more colors are requested than are available.

def diverging_palette(palette1, palette2, n=256, midpoint=0.5):
    palette2 = palette2[::-1]
    n1 = np.round(midpoint * n)
    n2 = np.round((1 - midpoint) * n)
    return palettes.linear_palette(palette1, n1) + palettes.linear_palette(palette2, n2)
@russellburdt russellburdt added the TRIAGE label Sep 25, 2019
@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 25, 2019

@bokeh/dev I am +1 on adding the diverging_palette palette, but +0 about adding the additional 256 color palettes (e.g. Reds256). Does anyone have strong feelings for/against?

@philippjfr

This comment has been minimized.

Copy link
Contributor

@philippjfr philippjfr commented Sep 25, 2019

Adding a utility to generate the 256 color palettes from the existing palettes seems useful, also +0 about actually hardcoding those. We ship exactly that in HoloViews already and expand them on the fly when requested.

@p-himik

This comment has been minimized.

Copy link
Contributor

@p-himik p-himik commented Sep 25, 2019

I would definitely like to see a function that is able to generate N colors from a specified palette. 256 or not 256 - any number that's relevant to my data.

On a side note, I would also rewrite the whole palette module since it's impossible to work with it in an IDE. But that's likely a separate task.

@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 25, 2019

@p-himik can you add an issue for your proposal? I think you mean changing to tuples instead of lists and then ditching the class-module business. That's fine but it should coincide with 2.0

@mattpap

This comment has been minimized.

Copy link
Contributor

@mattpap mattpap commented Sep 25, 2019

On a side note, I would also rewrite the whole palette module since it's impossible to work with it in an IDE. But that's likely a separate task.

We already did this in 2.0 branch, to allow static typing of that module.

@p-himik

This comment has been minimized.

Copy link
Contributor

@p-himik p-himik commented Sep 25, 2019

@mattpap landing-2.0, right? What IDE do you use? Because PyCharm still doesn't have any auto-completions for the palettes.

@russellburdt

This comment has been minimized.

Copy link
Contributor Author

@russellburdt russellburdt commented Sep 26, 2019

@p-himik Right now the linear_palette function will return a palette with an arbitrary number of colors less than or equal to an input palette. The max size in many cases is 256, and less than that in other cases. matplotlib implementation of palettes can return any arbitrary number (including above 256) from any palette. 256 is good upper limit from a practical point of view.

In [13]: palettes.linear_palette?
Signature: palettes.linear_palette(palette, n)
Docstring:
Generate a new palette as a subset of a given palette.

Given an input ``palette``, take ``n`` colors from it by dividing its
length into ``n`` (approximately) evenly spaced indices.
...
@p-himik

This comment has been minimized.

Copy link
Contributor

@p-himik p-himik commented Sep 26, 2019

@russellburdt

and less than that in other cases

That's exactly what the issue was for me. Only 6 palettes have 256 colors.

@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 26, 2019

OK, I think I am fine to just add the new 256 palettes. It's not like they will increase the size of the package to an appreciable degree. @russellburdt can you list all the ones you have in mind? The OP mentions "including but not limited to..."

@bryevdv bryevdv added type: feature and removed TRIAGE labels Sep 26, 2019
@bryevdv bryevdv added this to the 1.4 milestone Sep 26, 2019
@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 26, 2019

I've tentatively added this to the 1.4 milestone but it's fine if it slips. To get in 1.4 would need a PR before the end of next wee.

@jbednar

This comment has been minimized.

Copy link
Contributor

@jbednar jbednar commented Sep 26, 2019

How will we know when you'll next need to wee?

@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 26, 2019

k

@mattpap

This comment has been minimized.

Copy link
Contributor

@mattpap mattpap commented Sep 27, 2019

Because PyCharm still doesn't have any auto-completions for the palettes.

Right, I guess the module hack is still an issue. vscode, that I use, has the same problem.

@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 27, 2019

Right, I guess the module hack is still an issue. vscode, that I use, has the same problem.

Yes, I believe the proposal there is to replace the lists with tuples, so that they are immutable, and get rid of the module hack altogether.

@russellburdt

This comment has been minimized.

Copy link
Contributor Author

@russellburdt russellburdt commented Sep 27, 2019

@bryevdv @p-himik Any new palettes added for this issue #9241 will be tuples instead of lists. Would we be able to use a single PR to address this issue as well as #9248 ?

@p-himik

This comment has been minimized.

Copy link
Contributor

@p-himik p-himik commented Sep 27, 2019

@russellburdt Why would a single PR be better?
Anyway, I'm not sure because @bryevdv said that using tuples for palettes should coincide with 2.0 and this issue has 1.4 as its milestone.

@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 27, 2019

@russellburdt Yes, please follow the existing patterns in the module for all new palettes (i.e. return lists as all the existing ones do), we will make breaking changes to the structure of the module after the 1.4 release in a separate PR.

@russellburdt

This comment has been minimized.

Copy link
Contributor Author

@russellburdt russellburdt commented Sep 27, 2019

@bryevdv Got that, thanks.

@russellburdt

This comment has been minimized.

Copy link
Contributor Author

@russellburdt russellburdt commented Sep 29, 2019

@bryevdv @p-himik @mattpap Given that it is already agreed to rewrite the whole palettes module in 2.0 I think we can limit the scope of changes for this issue. I propose to add Reds256, Purples256, Blues256, Greens256, and Oranges256 palettes as lists of hex color strings (not tuples) and to add a diverging_palette function with signature diverging_palette(palette1, palette2, n=256, midpoint=0.5) that returns a generic symmetric or asymmetric diverging palette.

This will be my first open-source contribution, so I may have some process questions later on.

@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Sep 29, 2019

@russellburdt that sounds perfect, please let us know any questions we an answer, and thanks!

@bryevdv

This comment has been minimized.

Copy link
Member

@bryevdv bryevdv commented Oct 10, 2019

@russellburdt Just as an FYI, for this to go in 1.4 it would need to be submitted/merged befor the end of next week

@russellburdt

This comment has been minimized.

Copy link
Contributor Author

@russellburdt russellburdt commented Oct 17, 2019

PR has been submitted, hopefully in time for 1.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.