Search code examples
javascriptpython-3.xbokeh

Bokeh looking in temp files when trying to load new image using CustomJS


I am a novice at Bokeh and using CustomJS to define callbacks. I have written a code to make changes to sliders based on the value of other sliders. I now want to change the image displayed when the value of one of the sliders changes. However, when I run this callback, the image does not get displayed and within the console of the bokeh plot, I saw that bokeh is looking for some file in the temp files.

p = figure(title = 'foo', tools = 'pan, save, wheel_zoom,reset,crosshair', x_range = [0,10], y_range = [0,10])


slider1 = Slider(start=0, end=15, value=4,step=.1, title="Delta P")
slider2 = Slider(start=1400, end = 1800, value=1500, step = 10, title = "Mass Flow")

newdelta = 4
newflow = 1500
newCV = CV(4+newdelta, 4, 1.3,225.41, 0.9, newflow, 27.3,968) # CV is a function within my code elsewhere

source = ColumnDataSource(data=dict(url=['C:\\Users\\XXX\\test_sample.jpg'])) 

slider3 = Slider(start=-100, end = 2000, value=newCV, step = 1, title = "CV")
slider3.callback = CustomJS(args=dict(slider3=slider3, source=source), code="""


                                if (slider3.value < 0){
                                    source.data.url= "C:\\\\Users\\\\XXX\\\\new_sample.jpg";
                                    console.log(source.data['url']);
                                };
                                source.change.emit();

                                """)                          


p.image_url('url', source=source, x=2, y=8, w=6, h=6)


slider1.callback = CustomJS(args=dict(slider1=slider1,slider2=slider2,slider3=slider3), code="""
                            slider3.value= slider1.value + slider2.value;


                            """)

slider2.callback = CustomJS(args=dict(slider1=slider1,slider2=slider2,slider3=slider3), code="""
                            slider3.value= slider1.value + slider2.value;

                            """)

show(row(column(slider1, slider2,slider3),p))

I am not getting any errors in python but when the code is run and I change slider3 value to be less than 0, the console changes the source.data.url value to the new image but the image does not get loaded. Here is the error:

C:1 GET file:///C:/Users/XXX/AppData/Local/Temp/C net::ERR_FILE_NOT_FOUND
Image (async)
e @ bokeh-1.0.4.min.js:31
t._set_data @ bokeh-1.0.4.min.js:31
t.set_data @ bokeh-1.0.4.min.js:31
t.set_data @ bokeh-1.0.4.min.js:31
(anonymous) @ bokeh-1.0.4.min.js:31
t.emit @ bokeh-1.0.4.min.js:31
e.emit @ bokeh-1.0.4.min.js:31
c._setv @ bokeh-1.0.4.min.js:31
c.setv @ bokeh-1.0.4.min.js:31
set @ bokeh-1.0.4.min.js:31
t.compute_indices @ bokeh-1.0.4.min.js:31
(anonymous) @ bokeh-1.0.4.min.js:31
t.emit @ bokeh-1.0.4.min.js:31
e.emit @ bokeh-1.0.4.min.js:31
eval @ VM29:10
t.execute @ bokeh-1.0.4.min.js:31
t @ bokeh-widgets-1.0.4.min.js:31
(anonymous) @ bokeh-1.0.4.min.js:31
t._slide @ bokeh-widgets-1.0.4.min.js:31
(anonymous) @ bokeh-widgets-1.0.4.min.js:31
(anonymous) @ bokeh-widgets-1.0.4.min.js:32
(anonymous) @ bokeh-widgets-1.0.4.min.js:32
R @ bokeh-widgets-1.0.4.min.js:32
(anonymous) @ bokeh-widgets-1.0.4.min.js:32
T @ bokeh-widgets-1.0.4.min.js:32
O @ bokeh-widgets-1.0.4.min.js:32
e @ bokeh-widgets-1.0.4.min.js:32

Could someone please help me understand what is going wrong and how this can be corrected?


Solution

  • You cannot access local files directly from a web page.

    Solution 1: use bokeh serve and put the image data directly in the data source. You will have to use p.image_rgba instead of p.image_url.

    Example:

    import numpy as np
    from PIL import Image
    from bokeh.layouts import column
    from bokeh.models import Button, ColumnDataSource
    from bokeh.plotting import figure, curdoc
    
    
    def read_image_to_array(path):
        im = Image.open(path).convert('RGBA').transpose(Image.FLIP_TOP_BOTTOM)
        return np.asarray(im).view(np.uint32)
    
    
    ds = ColumnDataSource(data=dict(image=[], x=[], y=[], dw=[], dh=[]))
    
    p = figure()
    p.image_rgba(image='image', x='x', y='y', dw='dw', dh='dw', source=ds)
    b = Button(label='Set Image')
    
    
    def set_image():
        path = '...'
        img = read_image_to_array(path)
        dh, dw, _ = img.shape
        ds.data = dict(image=[img], x=[0], y=[0], dw=[dw], dh=[dh])
    
    
    b.on_click(set_image)
    
    curdoc().add_root(column(p, b))
    

    Solution 2: use a web server (even python -m http.server should suffice) and configure all URLs to be available through that web server.