How do you add a image to background on a interactive dashboard?

Hi All-

My ultimate goal is to be able to add these conditions to my interactive dashboard:

if xs == 'petal.length:
     if ys == 'petal.width:
        if "new-dropdown" == image1:
            "add image1 to plot"
        else if "new-dropdown" == image2:
            "add image2 to plot"

right now I am just trying to add an image to the background and my data disappears… Here is my code:

# Pandas for data management
import pandas as pd

# os methods for manipulating paths
from os.path import dirname, join

# Bokeh basics 
from bokeh.layouts import column, row
from bokeh.models import Select , ColumnDataSource, HoverTool
from bokeh.palettes import Category10_10
from bokeh.plotting import curdoc, figure

df = pd.read_csv("./Bokeh_App/Data/iris.csv", sep = ",")

SIZES = list(range(6, 22, 3))
COLORS = Category10_10 
N_SIZES = len(SIZES)
N_COLORS = len(COLORS)

#data clean up


columns = sorted(df.columns)
discrete = [x for x in columns if df[x].dtype == object]
continuous = [x for x in columns if x not in discrete]


def create_figure():
    xs = df[x.value].values
    ys = df[y.value].values
    x_title = x.value.title()
    y_title = y.value.title()

    TOOLTIPS = [
    ("x-axis", x_title),
    (x_title, "@xs"),
    ("y-axis", y_title),
    ("x-value", "@xs"),
    ("y-value", "@ys"),
    ("color", "@c"),
    ("size", "@sz")
    ]

    kw = dict()
    if x.value in discrete:
        kw['x_range'] = sorted(set(xs))
    if y.value in discrete:
        kw['y_range'] = sorted(set(ys))
    kw['title'] = "%s vs %s" % (x_title, y_title)

    hover = HoverTool(tooltips = TOOLTIPS)

    p = figure(plot_height=600, plot_width=800,tools= [hover], **kw)
    p.xaxis.axis_label = x_title
    p.yaxis.axis_label = y_title

    if x.value in discrete:
        p.xaxis.major_label_orientation = pd.np.pi / 4

    sz = 9
    if size.value != 'None':
        if len(set(df[size.value])) > N_SIZES:
            groups = pd.qcut(df[size.value].values, N_SIZES, duplicates='drop')
        else:
            groups = pd.Categorical(df[size.value])
        sz = [SIZES[xx] for xx in groups.codes]
    else:
        sz = [sz]*len(xs)

    c = "#31AADE"
    if color.value != 'None':
        if len(set(df[color.value])) > N_COLORS:
            groups = pd.qcut(df[color.value].values, N_COLORS, duplicates='drop')
        else:
            groups = pd.Categorical(df[color.value])
        c = [COLORS[xx] for xx in groups.codes]
    else:
        c = [c]*len(xs)
    
    source = ColumnDataSource(data=dict(xs = xs, ys = ys, c = [c]*len(xs), sz=[sz]*len(xs)))

    image = 'index.jpg'
    p.image_url([image], 1,6,2,3)

    p.circle(x='xs', y='ys', color='c', size='sz',source= source, line_color="white", alpha=0.6, hover_color='white', hover_alpha=0.5)

    return p


def update(attr, old, new):
    layout.children[1] = create_figure()


x = Select(title='X-Axis', value='petal.width', options=columns)
x.on_change('value', update)

y = Select(title='Y-Axis', value='petal.length', options=columns)
y.on_change('value', update)

size = Select(title='Size', value='None', options=['None'] + continuous)
size.on_change('value', update)

color = Select(title='Color', value='None', options=['None'] + continuous)
color.on_change('value', update)

controls = column(x, y, color, size, width=200)
layout = row(controls, create_figure())

curdoc().add_root(layout)
curdoc().title = "Crossfilter"

Thanks,
Chelsey

I think the problem in your case is that the path to the image is direct and you’re trying to run a bokeh server where the path has to be relative to the folder you’re trying to run.

Try this instead

image = './Bokeh_App/index.jpg'
p.image_url(url = [image],  x=1, y=6, w=2, h=3, anchor="bottom_left")

where x = image x-coordinate, y = image y-coordinate, w = width, h = height respectively.

Im having a issue now where my data will no longer show, nor the image.

import pandas as pd

# os methods for manipulating paths
from os.path import dirname, join

# Bokeh basics 
from bokeh.layouts import column, row
from bokeh.models import Select , ColumnDataSource
from bokeh.palettes import Category10_10
from bokeh.plotting import curdoc, figure

df = pd.read_csv("./Bokeh_App/Data/iris.csv", sep = ",")

SIZES = list(range(6, 22, 3))
COLORS = Category10_10 
N_SIZES = len(SIZES)
N_COLORS = len(COLORS)

#data clean up


columns = sorted(df.columns)
discrete = [x for x in columns if df[x].dtype == object]
continuous = [x for x in columns if x not in discrete]


def create_figure():
    xs = df[x.value].values
    ys = df[y.value].values
    x_title = x.value.title()
    y_title = y.value.title()

    TOOLTIPS = [
    ("x-axis", x_title),
    ("y-axis", y_title),
    ("x-value", "@xs"),
    ("y-value", "@ys"),
    ("color", "@c"),
    ("size", "@sz")
    ]

    kw = dict()
    if x.value in discrete:
        kw['x_range'] = sorted(set(xs))
    if y.value in discrete:
        kw['y_range'] = sorted(set(ys))
    kw['title'] = "%s vs %s" % (x_title, y_title)

    p = figure(plot_height=600, plot_width=800, tools='pan,box_zoom,hover,reset',tooltips = TOOLTIPS, **kw)
    p.xaxis.axis_label = x_title
    p.yaxis.axis_label = y_title

    if x.value in discrete:
        p.xaxis.major_label_orientation = pd.np.pi / 4

    sz = 9

    #updated else part

    if size.value != 'None':
        if len(set(df[size.value])) > N_SIZES:
            groups = pd.qcut(df[size.value].values, N_SIZES, duplicates='drop')
        else:
            groups = pd.Categorical(df[size.value])
        sz = [SIZES[xx] for xx in groups.codes]
    else:
        sz = [sz]*len(xs)

    #updated else part

    c = "#31AADE"
    if color.value != 'None':
        if len(set(df[color.value])) > N_COLORS:
            groups = pd.qcut(df[color.value].values, N_COLORS, duplicates='drop')
        else:
            groups = pd.Categorical(df[color.value])
        c = [COLORS[xx] for xx in groups.codes]
    else:
        c = [c]*len(xs)

    source = ColumnDataSource(data=dict(
        xs = xs,
        ys = ys ,
        c = [c]*len(xs),
        sz = [sz]*len(xs))
    )

    p.circle(x='xs', y='ys', color='c', size='sz',source= source, line_color="white", alpha=0.6, hover_color='white', hover_alpha=0.5)

    image = './Bokeh_App/index.jpg'
    p.image_url(url = [image],  x=1, y=6, w=2, h=3, anchor="bottom_left")
    
    return p


def update(attr, old, new):
    layout.children[1] = create_figure()


x = Select(title='X-Axis', value='petal.width', options=columns)
x.on_change('value', update)

y = Select(title='Y-Axis', value='petal.length', options=columns)
y.on_change('value', update)

size = Select(title='Size', value='None', options=['None'] + continuous)
size.on_change('value', update)

color = Select(title='Color', value='None', options=['None'] + continuous)
color.on_change('value', update)

controls = column(x, y, color, size, width=200)
layout = row(controls, create_figure())

curdoc().add_root(layout)
curdoc().title = "Crossfilter"