kepler.gl icon indicating copy to clipboard operation
kepler.gl copied to clipboard

Customize color scale and palette

Open heshan0131 opened this issue 7 years ago • 32 comments

Enter Custom Palatte

Color Palette customization (done) https://github.com/keplergl/kepler.gl/pull/601

User should be able to design custom color palette, they should be able to

  • Click using custom color palette to toggle color palette editor
  • Start from blank, or start from an existing palette, (advanced: paste an array of hex values into an input box)
  • Edit color value using a color picker, or input rgb, hex value
  • Add and remove colors
  • Drag to reorder colors

Color Value customization (in progress)

User should be able to import values next to each color, using dropdown for ordinal values and input box for numeric values. There will be a distribution graph for numeric values, user can drag the slider handle to adjust value range of each bin

Ordinal values

Screen Shot 2019-11-09 at 3 38 35 AM

Implementation Step:

  1. Store value color Map in layer.config.colorUI.colorRange.customPalette, create a new prop colorMap and save it as a JS Map
const colorMap = new Map([["foo", "#FFFFFF"], ["bar", "#000000"], ["foo1", "#FF0000"]]);

only store values manually selected by user. if user is using the "assign rest to one color" option, don't store all the rest of the values to the map, later when create color scale, use the .unknown() method to assign color to the rest of values.

  1. When calculate color based on custom color scale in layer.getVisChannelScale(base-layer.js). Use D3.ordinalScale and pass in the colorMap and a value for unknown
m = d3.scaleOrdinal()
  .domain(colorMap.keys())
  .range(colorMap.values())
.unknown('#fff000') // assign rest value to a color value 
Screen Shot 2019-11-09 at 3 39 12 AM [Numeric values]

Add more color scale options

  • Add log, sqrt and Jenkins natural break scale

Implementation steps:

  1. add log and sqrt scale (done) https://github.com/keplergl/kepler.gl/pull/670 1.5 add Jenkins natural breaks scale (in progress)
  2. Add a 'Use custom color palette ' toggle under the reserved toggle (done) https://github.com/keplergl/kepler.gl/pull/601
  3. Allow edit color value using a color picker, or input rgb, hex value (done) https://github.com/keplergl/kepler.gl/pull/601
  4. Add input box to custom value domain for each color (ordinal and numeric value has different input UI) (not started)
  5. Add distribution graph for numeric values (not started)

heshan0131 avatar Feb 28 '19 01:02 heshan0131

I would love this!

alejokp avatar Mar 20 '19 23:03 alejokp

I’d like to recommend react-color as a nice picker component :)

https://casesandberg.github.io/react-color/

chrisgervang avatar Jun 26 '19 03:06 chrisgervang

Hi, Will this also include manual color range specification? It would be very useful not only to have automatic color range determination such as by quantile or quantize but manual range specification like in QGIS. E. g. color "#FFC300" for values between 0 and 50, "#F1920E" for values between 51 and ... Thx, David

davidwedekind avatar Aug 19 '19 10:08 davidwedekind

@heshan0131 Do we have actions/helpers to change layer's color programmatically?

vohaha avatar Sep 23 '19 07:09 vohaha

landed

macrigiuseppe avatar Oct 04 '19 18:10 macrigiuseppe

Hi, First of all, the new color palette feature is awesome!!! Thanks for constantly improving kepler. I assumed there was also going to be a function to change the color scale, e. g. based on fixed custom intervals. Is such a function planned/ coming soon? Thanks for your answer. Best, David

DavidTrafi avatar Oct 09 '19 14:10 DavidTrafi

Adding value customization is in progress:

Screen Shot 2019-11-09 at 3 39 12 AM Screen Shot 2019-11-09 at 3 38 35 AM

heshan0131 avatar Nov 09 '19 11:11 heshan0131

Hi, I've found this value customization feature important for me. Are you still working on it? Maybe I could help?

Cheers Bartek

bartekmaciejewski avatar Dec 09 '19 10:12 bartekmaciejewski

Is the value customization still in progress?

miketsui3a avatar Apr 14 '20 04:04 miketsui3a

This got put away for a little while, we just resumed the work. Should come out in the next month or so

heshan0131 avatar May 14 '20 19:05 heshan0131

Hi, sorry to bother you, but I would like to ask you - are there any updates regarding to this function? Thank you very much in advance

Stepulin avatar Jun 24 '20 08:06 Stepulin

This got put away for a little while, we just resumed the work. Should come out in the next month or so

Hi heshan0131, sorry to bother you on this. Is the value customization still in the pipeline?

lucasvw avatar Jul 16 '20 08:07 lucasvw

Is the value customization ready to use?

zhenliangma avatar Sep 14 '20 03:09 zhenliangma

me too, I would love to use the value customization.

npahl avatar Sep 21 '20 06:09 npahl

Im waiting for this. it will be awesome...

EzequielPuerta avatar Nov 25 '20 15:11 EzequielPuerta

do we have any updates on this?

diego-ch avatar Nov 30 '20 16:11 diego-ch

I'm waiting for the opportunity to set the palette statically from min to max, and not relatively as now.

KrimsN avatar Dec 17 '20 03:12 KrimsN

do we have any updates on this?

jooglyp avatar Feb 02 '21 19:02 jooglyp

Really loved using Kepler so far!! Is there any updates on when value customization might be ready as it would be hugely helpful for my project?

nickbroom98 avatar Jun 04 '21 15:06 nickbroom98

This feature is going to be available in studio.unfolded.ai and after beta testing it will be merged into our open source project

macrigiuseppe avatar Jun 10 '21 20:06 macrigiuseppe

Kepler is great!! Is there any updates on when value customization might be ready in Kepler.gl?

yanzhegeo avatar Oct 14 '21 17:10 yanzhegeo

Any chance this will be available in the open source project soon? Would be greatly appreciated ;) Thanks to the team for an awesome tool!

gertstahl avatar Jun 09 '22 09:06 gertstahl

Up vote for this function too! Thanks a lot!

xiaofanliang avatar Sep 23 '22 02:09 xiaofanliang

I'm reading the comments before not sure if I missed something or if the update still hasn't been published yet.

Any updates on this update, please?

sinannoureddine avatar Oct 19 '22 11:10 sinannoureddine

Its almost 2023 and that feature still has not added :(

dancestorm avatar Nov 08 '22 11:11 dancestorm

This feature is going to be available in studio.unfolded.ai and after beta testing it will be merged into our open source project Any updates please? This is open since 2019. Just to know if we wait for it lol or we accept that it'll never be updated :(

sinannoureddine avatar Jan 24 '23 09:01 sinannoureddine

Hi @heshan0131 @sinannoureddine @dancestorm @xiaofanliang @mletic I have a separate column named as count Can you please tell me how to set the color for the count showing 0 as transaparent and the light color starts from 1 and ends with dark color for 100

New Project

image

KarthicKamalesh avatar Jun 06 '23 07:06 KarthicKamalesh

Could be relevant for someone working with Kepler in Jupiter. I managed to work out how to bind colors to custom value ranges using colorMap & colorLegends properties:

import pandas as pd
from keplergl import KeplerGl
from numpy import array

# Define color mapping routines ("less or equal" in this example)
class Mapper:

    def __init__(self):

        # Define custom palette & legend values
        self.__ranges = {
            2: { 'color':'#ff0000', 'legend':'<= 2' },
            3: { 'color':'#00ff00', 'legend':'<= 3' },
            4: { 'color':'#0000ff', 'legend':'> 3' }, # Key here must be >= than max value in dataset
        }

        self.__keys = array(list(self.__ranges.keys()))

    # Estimate color based on a value
    def __mapper(self, val:float) -> str:
        return self.__ranges[self.__keys[self.__keys >= val].min()]['color']
    
    # Prepare color map for Kepler config
    def get_color_map(self, for_values: pd.Series) -> list:
        return [[x,y] for x,y in zip(for_values, for_values.apply(self.__mapper))]
    
    # Prepare color legends for Kepler
    def get_color_legends(self) -> dict:
        return { v['color']:v['legend'] for _,v in self.__ranges.items() }
    
    # Prepare custom colors for Kepler
    def get_colors(self) -> list:
        return [v['color'] for _,v in self.__ranges.items()]

# Sample DataFrame
df = pd.DataFrame([[1,1,0],[2,2,0],[3,3,0],[4,4,0]], columns=['x','lon','lat'])

# Init Kepler
kgl = KeplerGl()
kgl.add_data(df)
kgl

# Pull out config
cfg = kgl.config
mapper = Mapper()

# Tweak it with the Mapper
color_range_for_layer = cfg['config']['visState']['layers'][0]['config']['visConfig']['colorRange']
color_range_for_layer['colors'] = mapper.get_colors()
color_range_for_layer['colorMap'] = mapper.get_color_map(df.x)
color_range_for_layer['colorLegends'] = mapper.get_color_legends()

# Re-Init Kepler and enjoy
kgl = KeplerGl(config=cfg)
kgl.add_data(df)
kgl

It's a bit of a hack of course but works fine for me. Not tested on really big datasets :)

kungf00man avatar Jun 19 '23 10:06 kungf00man

Thanks

KarthicKamalesh avatar Jun 23 '23 06:06 KarthicKamalesh

Note - the above code from kungf00man only works for version 0.3.2. Also - here's an enhacement to automate above code.

# modify the init method from mapper class from above 
import branca.colormap as cm
class Mapper:

    def __init__(self, vmin, vmax, n_steps):
        # Define custom palette & legend values
        stepsize = ((vmax+0.01)-vmin)/(n_steps-1)
        colormap_true_temp = cm.LinearColormap(colors=['blue', 'red'], vmin=vmin, vmax=vmax)
        ranges = {}
        for i in range(n_steps):
            value = np.round(vmin+stepsize*i, 2)
            color = colormap_true_temp(value)[:-2] ## remove the transparency 2 characters
            ranges[value] = {'color': str(color), 'legend': '<= ' + str(value)}
        self.__ranges = ranges

and then also modify the call from above to --> mapper = Mapper(vmin = 0, vmax = 5, n_steps=5)

ahinoamp avatar Aug 29 '23 09:08 ahinoamp