【问题标题】:Sliding through images with Bokeh Slider使用 Bokeh Slider 滑动图像
【发布时间】:2016-05-02 15:09:12
【问题描述】:

我正在尝试借助滑块无缝地传达大量科学数据。

我从 Bokeh 开始,对 JavaScript 几乎一无所知。我尝试设置第一种方法来滑过两个图像,但我无法刷新图像。

假设我的文件夹中有 1.png 和 2.png。

from bokeh.io import vform
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.plotting import Figure, output_file, show

output_file('image.html')

source = ColumnDataSource(data=dict(url=['1.png']))

p = Figure(x_range=(0,1), y_range=(0,1))

callbackimg = CustomJS(args=dict(source=source), code="""
    var data = source.get('data');
    var f = cb_obj.get('value')
    old = data['url'][0]
    data['url'][0]= old.replace("1","f")
    source.trigger('change');
""")

p.image_url('url',source=source, x=0, y=1,w=1,h=1)
slider = Slider(start=1, end=2, value=1, step=1, title="image number",     callback=callbackimg)

layout = vform(slider, p)
show(layout)

我将Bokeh Widget Doc 中的示例改编为滑块和 working with images in bokeh

我的想法是滑块,通过 callbackimg sn-p,将修改包含 url 的源,即要加载的图像的名称。 我现在认为,对源中的字符串进行简单访问,并通过滑块的当前值进行替换(因此当滑块从 1 变为 2 时,它应该从 1.png 跳到 2.png)应该做这个伎俩。

但是,一切都没有改变。我怀疑我在 Javascript sn-p 中做错了什么。

感谢您的反馈

编辑:我根据@bigreddot 的建议编辑了代码,但现在滑块在“2”位置滑动时只显示一个空图。 EDIT2:在我下面的回答中解决了这个问题

【问题讨论】:

    标签: javascript python slider interactive bokeh


    【解决方案1】:

    @bigreddot 答案是正确的,但是 var f 是一个数字,所以在替换中,我需要编写 f.toString(10)。 符合我要求的代码:

    from bokeh.io import vform
    from bokeh.models import CustomJS, ColumnDataSource, Slider
    from bokeh.plotting import Figure, output_file, show
    
    output_file('image.html')
    
    source = ColumnDataSource(data=dict(url=['1.png']))
    
    p = Figure(x_range=(0,1), y_range=(0,1))
    
    callbackimg = CustomJS(args=dict(source=source), code="""
        var data = source.get('data');
        var f = cb_obj.get('value')
        old = data['url'][0]
        data['url'][0]= old.replace("1",f.toString(10))
        source.trigger('change');
    """)
    
    p.image_url('url',source=source, x=0, y=1,w=1,h=1)
    slider = Slider(start=1, end=2, value=1, step=1, title="image number",     callback=callbackimg)
    
    layout = vform(slider, p)
    show(layout)
    

    【讨论】:

      【解决方案2】:

      问题是这样的:

      url = data['url'][0]
      url.replace("1","f")
      

      replace 方法返回一个 new 字符串(您会立即将其丢弃),因此您实际上并未更改列数据源中的任何内容。你需要这样的东西:

      old = data['url'][0]
      data['url'] = old.replace("1","f")
      

      【讨论】:

        【解决方案3】:

        我创建了一个示例示例,其中图像根据滑块值进行更改。如果滑块值为 1,则应用将显示 map-marker.png 图像,如果值为 2,则应用将显示 google_logo.png 图像。

        在 Div 的帮助下,您可以非常轻松地完成这项任务。

        地图标记.png

        google_logo.png

        步骤:

        1. /usr/local/lib/python2.7/dist-packages/bokeh/server/static这个路径中创建一个名为“image”的文件夹
        2. 在上述位置创建文件夹后,将 google_logo.png 和 map-marker.png 图像复制到 /usr/local/lib/python2.7/dist-packages/bokeh/server/static/image 这个位置。并将以下代码保存为 app.py 并使用 bokeh serve app.py --show 命令运行它。

          from bokeh.io import curdoc
          from bokeh.layouts import row
          from bokeh.models.widgets import Slider, Div
          
          def change_img(attr, old, new):
              if slider.value == 1:
                  logo.text = """<img src="static/image/map-marker.png"  alt="logo">"""
              else:
                  logo.text = """<img src="static/image/google_logo.png"  alt="logo">"""
          
          slider = Slider(start=1, end=2, value=1, title="image number")
          slider.on_change('value', change_img)
          logo = Div(text="""<img src="static/image/logo.png"  alt="logo">""")
          
          curdoc().add_root(row(slider,logo))
          curdoc().title = "Image Demo"
          

        app.py 工作

        在散景版本 0.12.13 上测试

        【讨论】:

        • 作为此解决方案的补充,logo.text 可以动态更改,将其视为常规 Python 字符串,例如:"""&lt;img src="static/image/{}.png" alt="logo"&gt;""".format(file_name)(在 Python 3.7.3 和 bokeh 1.2.0 中测试)跨度>
        【解决方案4】:

        另一种选择是预先创建一个包含所有图像 url 的数据源,并使用滑块选择正确的图像。

        给定图像名称:

        import pandas as pd
        imgs = ['1.png', '2.png', '3.png']
        df = pd.DataFrame(imgs, columns=['imgs'])
        print(df.head())
        
             imgs
        0   1.png
        1   2.png
        2   3.png
        

        你可以这样做:

        from bokeh.layouts import layout
        from bokeh.plotting import figure, show
        from bokeh.models import CustomJS, Slider, ColumnDataSource
        
        source = ColumnDataSource(df)
        p = figure(x_range=(0,1), y_range=(0,1))
        im = p.image_url(url=[source.data['imgs'][0]], x=0, y=1, w=1, h=1)
        
        cb = CustomJS(args=dict(im=im, source=source), code="""
            im.data_source.data['url'] = [source.data['imgs'][cb_obj.value]];
            im.data_source.change.emit();
        """)
        slider = Slider(start=0, end=2, value=0, step=1, title="image number", callback=cb)
        show(layout([slider, p]))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-01
          • 2016-11-23
          相关资源
          最近更新 更多