☰Read-only archive⌕
Looking for help with Bokeh?

This is a read-only archive. Ask questions and join the conversation on GitHub.

Visit Community Support on GitHub →
Archived discussions · Captured October 28, 2026

Possible to update a image_rgba on change of a widget?

Community Support
eburgess
eburgess

I see plenty of great examples of how to update glyphs on a plot following an on change of a widget by altering the column data source object. My question is can we update an image in the same way? figure.image_rgba takes a numpy array, not a ColumnDataSource. Is it possible to just replot a new image by specifying a new numpy array when an on_change event is triggered? And if so is there any difference in this functionality compared to glyphs that use a ColumnDataSource? Thanks!

⌁   Link to post
Tyler_Nickerson
Tyler_Nickerson

To the best of my knowledge, all the plotting glyphs should be compatible with column data source. With glyphs like image_rgba, you have to assign a list containing your array to a column of your column data source. Currently, this will only work if the column containing your image array is named ‘image’ — this is a closed issue and will be fixed in 0.12.5. From there, updating the plot follows the same pattern or altering the column data source model within a callback.

Here is an example illustrating updating an image_rgba glyph, using bokeh server. Largely borrowing from the example here.

from [bokeh.io](http://bokeh.io) import curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
import numpy as np
import pandas as pd
N = 20
img = np.empty((N, N), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((N, N, 4
))
for i in range(N):
for j in range(N):
view[i, j, 0] = int(i/N*255        )
view[i, j, 1] = 158
        view[i, j, 2] = int(j/N*255        )
view[i, j, 3] = 255

# assign a list containing our image to column data source column
source = ColumnDataSource({'image'
: [img]})
p = figure(x_range=(0,10), y_range=(0,10
))
p.image_rgba(image='image', x=0, y=0, dw=10, dh=10
, source=source)
slide = Slider(start=0, end=500, step=10, value=0
)
layout = column(p, slide)
# update image on callback
def update(attr, old, new):
    # create a new image based on slider widget value
    new_image = img
new_view = new_image.view(dtype=np.uint8).reshape((N, N, 4    ))
new_view[:, :, 0] = (new_view[:, :, 0] + slide.value) % 255
    new_view[:, :, 2] = (new_view[:, :, 2] + slide.value) % 255
    # update column data source
    source.data = {'image'
: [new_image]}
slide.on_change('value'
, update)
curdoc().add_root(layout)

​

···

On Tue, Feb 14, 2017 at 3:40 PM, eburgess@airsci.com wrote:

I see plenty of great examples of how to update glyphs on a plot following an on change of a widget by altering the column data source object. My question is can we update an image in the same way? figure.image_rgba takes a numpy array, not a ColumnDataSource. Is it possible to just replot a new image by specifying a new numpy array when an on_change event is triggered? And if so is there any difference in this functionality compared to glyphs that use a ColumnDataSource? Thanks!

–

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to bokeh+unsubscribe@continuum.io.

To post to this group, send email to bokeh@continuum.io.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/8478457a-9b5f-463f-9ed5-d8434cbe3b65%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

⌁   Link to post
eburgess
eburgess

Awesome thanks Tyler! Just for others, one small correction to make your script above work is it seems we still want to start the ColumnDataSource with an empty image, {‘image’:} and then update it with update. Thanks, again!

···

On Wednesday, February 15, 2017 at 11:48:02 AM UTC-8, Tyler Nickerson wrote:

To the best of my knowledge, all the plotting glyphs should be compatible with column data source. With glyphs like image_rgba, you have to assign a list containing your array to a column of your column data source. Currently, this will only work if the column containing your image array is named ‘image’ — this is a closed issue and will be fixed in 0.12.5. From there, updating the plot follows the same pattern or altering the column data source model within a callback.

Here is an example illustrating updating an image_rgba glyph, using bokeh server. Largely borrowing from the example here.

from [bokeh.io](http://bokeh.io) import curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
import numpy as np
import pandas as pd
N = 20
img = np.empty((N, N), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((N, N, 4
))
for i in range(N):
for j in range(N):
view[i, j, 0] = int(i/N*255        )
view[i, j, 1] = 158
        view[i, j, 2] = int(j/N*255        )
view[i, j, 3] = 255

# assign a list containing our image to column data source column
source = ColumnDataSource({'image'
: [img]})
p = figure(x_range=(0,10), y_range=(0,10
))
p.image_rgba(image='image', x=0, y=0, dw=10, dh=10
, source=source)
slide = Slider(start=0, end=500, step=10, value=0
)
layout = column(p, slide)
# update image on callback
def update(attr, old, new):
    # create a new image based on slider widget value
    new_image = img
new_view = new_image.view(dtype=np.uint8).reshape((N, N, 4    ))
new_view[:, :, 0] = (new_view[:, :, 0] + slide.value) % 255
    new_view[:, :, 2] = (new_view[:, :, 2] + slide.value) % 255
    # update column data source
    source.data = {'image'
: [new_image]}
slide.on_change('value'
, update)
curdoc().add_root(layout)

​

On Tue, Feb 14, 2017 at 3:40 PM, ebur...@airsci.com wrote:

I see plenty of great examples of how to update glyphs on a plot following an on change of a widget by altering the column data source object. My question is can we update an image in the same way? figure.image_rgba takes a numpy array, not a ColumnDataSource. Is it possible to just replot a new image by specifying a new numpy array when an on_change event is triggered? And if so is there any difference in this functionality compared to glyphs that use a ColumnDataSource? Thanks!

–

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to bokeh+un...@continuum.io.

To post to this group, send email to bo...@continuum.io.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/8478457a-9b5f-463f-9ed5-d8434cbe3b65%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

⌁   Link to post
Tyler_Nickerson
Tyler_Nickerson

I’m glad I could help. Sorry, about the example not working! I removed a line from the callback function that I thought was redundant, but it had the necessary side effect of assigning a copy of img to new_img… Adding the copy method to the first line of the callback function will fix the issue as well. This approach will work with initializing the the column data source with {'image': [img]}. Here’s the modified callback function:

def update(attr, old, new):
    # create a new image based on slider widget value
    new_image = img.copy() new_view = new_image.view(dtype=np.uint8).reshape((N, N, 4    ))
new_view[:, :, 0] = (new_view[:, :, 0] + slide.value) % 255
    new_view[:, :, 2] = (new_view[:, :, 2] + slide.value) % 255

    # update column data source
    source.data = {'image': [new_image]}
`

​

···

On Thu, Feb 16, 2017 at 9:01 AM, eburgess@airsci.com wrote:

Awesome thanks Tyler! Just for others, one small correction to make your script above work is it seems we still want to start the ColumnDataSource with an empty image, {‘image’:} and then update it with update. Thanks, again!

On Wednesday, February 15, 2017 at 11:48:02 AM UTC-8, Tyler Nickerson wrote:

To the best of my knowledge, all the plotting glyphs should be compatible with column data source. With glyphs like image_rgba, you have to assign a list containing your array to a column of your column data source. Currently, this will only work if the column containing your image array is named ‘image’ — this is a closed issue and will be fixed in 0.12.5. From there, updating the plot follows the same pattern or altering the column data source model within a callback.

Here is an example illustrating updating an image_rgba glyph, using bokeh server. Largely borrowing from the example here.

from [bokeh.io](http://bokeh.io) import curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
import numpy as np
import pandas as pd
N = 20
img = np.empty((N, N), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((N, N, 4
))
for i in range(N):
for j in range(N):
view[i, j, 0] = int(i/N*255        )
view[i, j, 1] = 158
        view[i, j, 2] = int(j/N*255        )
view[i, j, 3] = 255

# assign a list containing our image to column data source column
source = ColumnDataSource({'image'
: [img]})
p = figure(x_range=(0,10), y_range=(0,10
))
p.image_rgba(image='image', x=0, y=0, dw=10, dh=10
, source=source)
slide = Slider(start=0, end=500, step=10, value=0
)
layout = column(p, slide)
# update image on callback
def update(attr, old, new):
    # create a new image based on slider widget value
    new_image = img
new_view = new_image.view(dtype=np.uint8).reshape((N, N, 4    ))
new_view[:, :, 0] = (new_view[:, :, 0] + slide.value) % 255
    new_view[:, :, 2] = (new_view[:, :, 2] + slide.value) % 255
    # update column data source
    source.data = {'image'
: [new_image]}
slide.on_change('value'
, update)
curdoc().add_root(layout)

​

On Tue, Feb 14, 2017 at 3:40 PM, ebur...@airsci.com wrote:

I see plenty of great examples of how to update glyphs on a plot following an on change of a widget by altering the column data source object. My question is can we update an image in the same way? figure.image_rgba takes a numpy array, not a ColumnDataSource. Is it possible to just replot a new image by specifying a new numpy array when an on_change event is triggered? And if so is there any difference in this functionality compared to glyphs that use a ColumnDataSource? Thanks!

–

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to bokeh+un...@continuum.io.

To post to this group, send email to bo...@continuum.io.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/8478457a-9b5f-463f-9ed5-d8434cbe3b65%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

–

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to bokeh+unsubscribe@continuum.io.

To post to this group, send email to bokeh@continuum.io.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/3a8ca68e-f8d4-414a-9312-7112f9c4e574%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

⌁   Link to post
eburgess
eburgess

Ah ok this makes more sense. Thanks Tyler!

···

On Thursday, February 16, 2017 at 12:19:12 PM UTC-8, Tyler Nickerson wrote:

I’m glad I could help. Sorry, about the example not working! I removed a line from the callback function that I thought was redundant, but it had the necessary side effect of assigning a copy of img to new_img… Adding the copy method to the first line of the callback function will fix the issue as well. This approach will work with initializing the the column data source with {'image': [img]}. Here’s the modified callback function:

def update(attr, old, new):
    # create a new image based on slider widget value
    new_image = img.copy() new_view = new_image.view(dtype=np.uint8).reshape((N, N, 4    ))
new_view[:, :, 0] = (new_view[:, :, 0] + slide.value) % 255
    new_view[:, :, 2] = (new_view[:, :, 2] + slide.value) % 255

    # update column data source
    source.data = {'image': [new_image]}
`

​

On Thu, Feb 16, 2017 at 9:01 AM, ebur...@airsci.com wrote:

Awesome thanks Tyler! Just for others, one small correction to make your script above work is it seems we still want to start the ColumnDataSource with an empty image, {‘image’:} and then update it with update. Thanks, again!

On Wednesday, February 15, 2017 at 11:48:02 AM UTC-8, Tyler Nickerson wrote:

To the best of my knowledge, all the plotting glyphs should be compatible with column data source. With glyphs like image_rgba, you have to assign a list containing your array to a column of your column data source. Currently, this will only work if the column containing your image array is named ‘image’ — this is a closed issue and will be fixed in 0.12.5. From there, updating the plot follows the same pattern or altering the column data source model within a callback.

Here is an example illustrating updating an image_rgba glyph, using bokeh server. Largely borrowing from the example here.

from [bokeh.io](http://bokeh.io) import curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
import numpy as np
import pandas as pd
N = 20
img = np.empty((N, N), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((N, N, 4
))
for i in range(N):
for j in range(N):
view[i, j, 0] = int(i/N*255        )
view[i, j, 1] = 158
        view[i, j, 2] = int(j/N*255        )
view[i, j, 3] = 255

# assign a list containing our image to column data source column
source = ColumnDataSource({'image'
: [img]})
p = figure(x_range=(0,10), y_range=(0,10
))
p.image_rgba(image='image', x=0, y=0, dw=10, dh=10
, source=source)
slide = Slider(start=0, end=500, step=10, value=0
)
layout = column(p, slide)
# update image on callback
def update(attr, old, new):
    # create a new image based on slider widget value
    new_image = img
new_view = new_image.view(dtype=np.uint8).reshape((N, N, 4    ))
new_view[:, :, 0] = (new_view[:, :, 0] + slide.value) % 255
    new_view[:, :, 2] = (new_view[:, :, 2] + slide.value) % 255
    # update column data source
    source.data = {'image'
: [new_image]}
slide.on_change('value'
, update)
curdoc().add_root(layout)

​

On Tue, Feb 14, 2017 at 3:40 PM, ebur...@airsci.com wrote:

I see plenty of great examples of how to update glyphs on a plot following an on change of a widget by altering the column data source object. My question is can we update an image in the same way? figure.image_rgba takes a numpy array, not a ColumnDataSource. Is it possible to just replot a new image by specifying a new numpy array when an on_change event is triggered? And if so is there any difference in this functionality compared to glyphs that use a ColumnDataSource? Thanks!

–

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to bokeh+un...@continuum.io.

To post to this group, send email to bo...@continuum.io.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/8478457a-9b5f-463f-9ed5-d8434cbe3b65%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

–

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to bokeh+un...@continuum.io.

To post to this group, send email to bo...@continuum.io.

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/3a8ca68e-f8d4-414a-9312-7112f9c4e574%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

⌁   Link to post
PBrockmann
PBrockmann

Thanks. Very useful. Here is a version where I control contrast and brightness with 2 sliders.

Any idea about how to update an image from a FileInput widget ?

Here a piece of code to run with bokeh server.

from bokeh.layouts import column
from bokeh.models import FileInput, Slider, LinearAxis
from bokeh.plotting import figure, curdoc, ColumnDataSource

import os
import cv2

#=============================================================
alphaLevel = 1.0 # Contrast control
betaLevel = 0 # Brightness control

#=============================================================
file_input = FileInput()
def upload_data(attr, old, new):
    sourceImage.data = {'image': [file_input]}
    # ???????

file_input.on_change('value', upload_data)

#=============================================================
imageFileName = 'myapp2/static/BEL17-2-2_1.66x_milieu0001.png'
img0 = cv2.imread(imageFileName)
img = cv2.flip(img0, 0)     # https://github.com/bokeh/bokeh/issues/1666
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
adjusted = cv2.convertScaleAbs(gray, alpha=alphaLevel, beta=betaLevel)

sourceImage = ColumnDataSource({'image': [adjusted]})

#=============================================================
def callbackSliderAlphaBeta(attr, old, new):
    alphaLevel = sliderAlpha.value
    betaLevel = sliderBeta.value
    print("Contrast level (1.0-3.0): %.1f" %(alphaLevel))
    print("Brightness level: %d" %(betaLevel))
    adjusted = cv2.convertScaleAbs(gray, alpha=alphaLevel, beta=betaLevel)
    sourceImage.data = {'image': [adjusted]}

sliderAlpha = Slider(width=300, start=1.0, end=3.0, value=1.0, step=.1, title="Contrast")     # Contrast control (1.0:3.0)
sliderAlpha.on_change('value', callbackSliderAlphaBeta)

sliderBeta = Slider(width=300, start=-100, end=100, value=0, step=5, title="Brightness")     # Brightness control (-100:100)
sliderBeta.on_change('value', callbackSliderAlphaBeta)

#=============================================================
h, w, c = img.shape
print(w,h)

plot_width = 800
ratio = plot_width/w

plot = figure(
    plot_width = plot_width,
    plot_height = int(h*ratio),
    x_range=(1,w),
    y_range=(1,h),
    tools = "pan,wheel_zoom,box_zoom,reset,save",
    toolbar_location = "above",
    active_scroll = "wheel_zoom",
    sizing_mode = "fixed" ,
    title = os.path.basename(imageFileName)
)

plot.add_layout(LinearAxis(), 'above')
plot.add_layout(LinearAxis(), 'right')

imagePlot = plot.image(image='image', source=sourceImage, x=0, y=0, dw=w, dh=h, palette='Greys256')

#=============================================================
curdoc().add_root(column(plot, sliderAlpha, sliderBeta, file_input))
⌁   Link to post

End of archived discussion · Replies are disabled