color_sliders.py — Anaconda Enterprise 4.4 documentation

Anaconda Enterprise: Documentation

# color_sliders.py

    import colorsys
    import yaml

    from bokeh.layouts import column, row, widgetbox
    from bokeh.models import ColumnDataSource, HoverTool, CustomJS, Slider
    from bokeh.plotting import figure, output_file, show, curdoc
    from bokeh.themes import Theme

    # for plot 2: create colour spectrum of resolution N and brightness I, return as list of decimal RGB value tuples
    def generate_color_range(N, I):
        HSV_tuples = [ (x*1.0/N, 0.5, I) for x in range(N) ]
        RGB_tuples = map(lambda x: colorsys.hsv_to_rgb(*x), HSV_tuples)
        for_conversion = []
        for RGB_tuple in RGB_tuples:
            for_conversion.append((int(RGB_tuple[0]*255), int(RGB_tuple[1]*255), int(RGB_tuple[2]*255)))
        hex_colors = [ rgb_to_hex(RGB_tuple) for RGB_tuple in for_conversion ]
        return hex_colors, for_conversion

    # convert RGB tuple to hexadecimal code
    def rgb_to_hex(rgb):
        return '#%02x%02x%02x' % rgb

    # convert hexadecimal to RGB tuple
    def hex_to_dec(hex):
        red = ''.join(hex.strip('#')[0:2])
        green = ''.join(hex.strip('#')[2:4])
        blue = ''.join(hex.strip('#')[4:6])
        return (int(red, 16), int(green, 16), int(blue,16))

    # plot 1: create a color block with RGB values adjusted with sliders

    # initialise a white block for the first plot
    hex_color = rgb_to_hex((255, 255, 255))

    # initialise the text color as black. This will be switched to white if the block color gets dark enough
    text_color = '#000000'

    # create a data source to enable refreshing of fill & text color
    source = ColumnDataSource(data=dict(color=[hex_color], text_color=[text_color]))

    # create first plot, as a rect() glyph and centered text label, with fill and text color taken from source
    p1 = figure(x_range=(-8, 8), y_range=(-4, 4),
                plot_width=600, plot_height=300,
                title='move sliders to change', tools='')

    p1.rect(0, 0, width=18, height=10, fill_color='color',
            line_color = 'black', source=source)

    p1.text(0, 0, text='color', text_color='text_color',
            alpha=0.6667, text_font_size='36pt', text_baseline='middle',
            text_align='center', source=source)

    # the callback function to update the color of the block and associated label text
    # NOTE: the JS functions for converting RGB to hex are taken from the excellent answer
    # by Tim Down at http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb
    callback = CustomJS(args=dict(source=source), code="""
        function componentToHex(c) {
            var hex = c.toString(16);
            return hex.length == 1 ? "0" + hex : hex;
        }
        function rgbToHex(r, g, b) {
            return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
        }
        function toInt(v) {
           return v | 0;
        }
        var data = source.data;
        color = data['color'];
        text_color = data['text_color'];
        var R = toInt(red_slider.value);
        var G = toInt(green_slider.value);
        var B = toInt(blue_slider.value);
        color[0] = rgbToHex(R, G, B);
        text_color[0] = '#ffffff';
        if ((R > 127) || (G > 127) || (B > 127)) {
            text_color[0] = '#000000';
        }
        source.change.emit();
    """)

    # create slider tool objects with a callback to control the RGB levels for first plot
    SLIDER_ARGS = dict(start=0, end=255, value=255, step=1, callback=callback)

    red_slider = Slider(title="R", **SLIDER_ARGS)
    callback.args['red_slider'] = red_slider

    green_slider = Slider(title="G", **SLIDER_ARGS)
    callback.args['green_slider'] = green_slider

    blue_slider = Slider(title="B", **SLIDER_ARGS)
    callback.args['blue_slider'] = blue_slider

    # plot 2: create a color spectrum with a hover-over tool to inspect hex codes

    brightness = 0.8 # change to have brighter/darker colors
    crx = list(range(1,1001)) # the resolution is 1000 colors
    cry = [ 5 for i in range(len(crx)) ]
    crcolor, crRGBs = generate_color_range(1000,brightness) # produce spectrum

    # make data source object to allow information to be displayed by hover tool
    crsource = ColumnDataSource(data=dict(x=crx, y=cry, crcolor=crcolor, RGBs=crRGBs))

    # create second plot
    p2 = figure(x_range=(0,1000), y_range=(0,10),
                plot_width=600, plot_height=150,
                tools='hover', title='hover over color')

    color_range1 = p2.rect(x='x', y='y', width=1, height=10,
                           color='crcolor', source=crsource)

    # set up hover tool to show color hex code and sample swatch
    p2.select_one(HoverTool).tooltips = [
        ('color', '$color[hex, rgb, swatch]:crcolor'),
        ('RGB levels', '@RGBs')
    ]

    # theme everything for a cleaner look
    curdoc().theme = Theme(json=yaml.load("""
    attrs:
        Plot:
            toolbar_location: null
        Grid:
            grid_line_color: null
        Axis:
            axis_line_color: null
            major_label_text_color: null
            major_tick_line_color: null
            minor_tick_line_color: null
    """))

    layout = row(
        widgetbox(red_slider, green_slider, blue_slider),
        column(p1, p2)
    )

    output_file("color_sliders.html", title="color_sliders.py example")

    show(layout)