草庐IT

javascript - Bokeh :在图像图中实现自定义 javascript

coder 2023-08-23 原文

我试图在 Bokeh 中结合这两个示例:

http://docs.bokeh.org/en/latest/docs/gallery/image.html http://docs.bokeh.org/en/latest/docs/user_guide/interaction/callbacks.html#customjs-for-widgets

这个想法看起来很简单。我想绘制第一个链接中显示的图像,然后使用交互式 slider 改变正弦函数的频率:

import numpy as np

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


N = 10

x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)  

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

source = ColumnDataSource(data={'d': d, 'x': x, 'y': y})

p = figure(x_range=[0, 10], y_range=[0, 10])
p.image([source.data['d']], x=[0], y=[0], dw=[10], dh=[10], palette="Spectral11")

callback = CustomJS(args=dict(source=source), code="""
        var data = source.get('data');
        var f = cb_obj.get('value')
        x = data['x']
        y = data['y']
        d = data['d']
        for (i = 0; i < x.length; i++) {
            for (i = 0; i < x.length; i++){
                d[i][j] = Math.sin(f*x[i])*Math.cos(y[j])
        }
        source.trigger('change');
    """)

slider = Slider(start=0.1, end=4, value=1, step=.1, title="angular frequency", callback=callback)

layout = vform(slider, p)

show(layout)

图表绘制正确,但图像永远不会更新。问题几乎肯定存在于我如何绘制图像:

p.image([source.data['d']], x=[0], y=[0], dw=[10], dh=[10], palette="Spectral11")

我不认为这是将绘图正确附加到源对象的方式。我只是传入一个数组,这解释了为什么当源更改时绘图没有更新,但我不确定图像函数的正确方法是什么。如果我将语句更改为:

p.image(['d'], x=[0], y=[0], dw=[10], dh=[10], source=source, palette="Spectral11")

它不会正确绘制。我不确定这只是语法问题还是更深层次的问题。任何指针将不胜感激。提前致谢。

最佳答案

这几天我一直在处理类似的问题。最后我成功了。首先,请注意 ColumnDataSource 函数中的方括号 []。数据允许多个图像。因此,在回调函数中,您应该使用 [0] 来获取一张图像的数据。此外,在图像源中使用“x”和“y”与图像 x=[0] 和 y[0] 的位置冲突,因此我使用了 xx 和 yy。我想提一下,我从 tobyhodges color_sliders.py 的示例中借用了代码:一种将 slider 信息推送到已定义的回调函数的方法。这里的代码:

import numpy as np
from bokeh.plotting import figure, show, output_file
from bokeh.models import CustomJS, ColumnDataSource, Slider
from bokeh.io import vform

N = 100

x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)  

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

source = ColumnDataSource(data={'d': [d], 'xx': [x], 'yy': [y]})

p = figure(x_range=[0, 10], y_range=[0, 10])
p.image(image="d", x=[0], y=[0], dw=[10], dh=[10], palette="Spectral11",source=source)

callback = CustomJS(args=dict(source=source), code="""
        var xx = source.get('data')['xx'][0];
        var yy = source.get('data')['yy'][0];
        var d = source.get('data')['d'][0];
        var f = slider.get('value');
        for (var i = 0; i < xx.length; i++) {
            for (var j = 0; j < yy.length; j++){
                d[i][j] = Math.sin(f * xx[i]) * Math.cos(yy[j]);
            }
        }
        source.trigger('change');
    """)

slider = Slider(start=0.1, end=4, value=1, step=.1, title="angular frequency", callback=callback)
callback.args['slider'] = slider
layout = vform(slider, p)
show(layout)

为了避免在最新版本的 bokeh(我刚刚安装的版本是 0.12.3)中出现弃用警告,我对这段代码进行了如下修改。在此代码中,我没有为图像使用数据源。在 CustomJS 中,我传递图像句柄“im”并将数据源作为 im.data_source

import numpy as np
import bokeh
import bokeh.plotting

N = 100

x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)  

source = bokeh.models.ColumnDataSource(data={'x': [x], 'y': [y]})

p = bokeh.plotting.figure(x_range=[0, 10], y_range=[0, 10])
im = p.image(image=[d], x=[0], y=[0], dw=[10], dh=[10], palette="Spectral11")

callback = bokeh.models.CustomJS(args=dict(source=source,im=im), code="""
        var x = source.data['x'][0];
        var y = source.data['y'][0];
        var image_source = im.data_source;
        var d = image_source.data['image'][0];
        var f = slider.value;
        for (var i = 0; i < x.length; i++) {
            for (var j = 0; j < y.length; j++){
                d[i][j] = Math.sin(f * x[i]) * Math.cos(f * y[j]);
            }
        }
        image_source.trigger('change');
    """)

slider = bokeh.models.Slider(start=0.1, end=4, value=1, step=.1, 
                             title="angular frequency", callback=callback)
callback.args['slider'] = slider
layout = bokeh.models.layouts.Column(slider, p)

bokeh.io.output_file("image.html", title="image.py example")
bokeh.io.save(layout)

Bokeh 版本 0.12.4 的更新:

更改:现在的输出是针对 Jupyter 笔记本的。获取html页面,按照之前的版本即可。此 Bokeh 版本的新功能:JavaScript 上的数组现在是一维数组。

import numpy as np
import bokeh
import bokeh.plotting

N = 100

x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)  

source = bokeh.models.ColumnDataSource(data={'x': [x], 'y': [y]})

p = bokeh.plotting.figure(plot_width=300, plot_height=300,x_range=[0, 10], y_range=[0, 10])
im = p.image(image=[d], x=[0], y=[0], dw=[10], dh=[10], palette="Spectral11")

callback = bokeh.models.CustomJS(args=dict(source=source,im=im), code="""
        var x = source.data['x'][0];
        var y = source.data['y'][0];
        var image_source = im.data_source;
        var d = image_source.data['image'][0];
        var f = slider.value;
        for (var j = 0; j < y.length; j++){
            for (var i = 0; i < x.length; i++) {
                d[j*y.length + i] = Math.sin(f * x[i]) * Math.cos(f * y[j]);
            }
        }
        image_source.trigger('change');
    """)

slider = bokeh.models.Slider(start=0.1, end=4, value=1, step=.1,
                             title="angular frequency",callback=callback)
callback.args['slider'] = slider
layout = bokeh.models.layouts.Row(p,slider)

bokeh.io.output_notebook()
bokeh.io.show(layout)

Bokeh 版本 0.12.15 的更新:

import numpy as np
import bokeh
import bokeh.plotting

N = 100

x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)  

source = bokeh.models.ColumnDataSource(
    data=dict(values=[d],x_vals=[x],y_vals=[y]))

p = bokeh.plotting.figure(plot_width=300, plot_height=300,
    x_range=[0, 10], y_range=[0, 10])
p.image(image='values', x=0, y=0, dw=10, dh=10, 
    palette="Spectral11", source=source)

callback = bokeh.models.CustomJS(args=dict(source=source), code="""
    var f = slider.value;
    var x = source.data['x_vals'][0];
    var y = source.data['y_vals'][0];
    var d = source.data['values'][0];
    for (var j = 0; j < y.length; j++){
        for (var i = 0; i < x.length; i++) {
            d[j*y.length + i] = Math.sin(f*x[i]) * Math.cos(f*y[j]);
        }
    }
    source.change.emit();
    """)

slider = bokeh.models.Slider(start=0.1, end=4, value=1, step=.1,
    title="angular frequency",callback=callback)
callback.args['slider'] = slider
layout = bokeh.models.layouts.Row(p,slider)

bokeh.io.output_notebook()
bokeh.io.show(layout)

Bokeh 版本 2.4.2 的更新:

最近的版本有些变化。适用于版本 2.4.2(最新版本为 2022 年 2 月)的代码如下。

import numpy as np
import bokeh
import bokeh.plotting

N = 100

x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = np.sin(xx)*np.cos(yy)  

source = bokeh.models.ColumnDataSource(data=dict(
             x_values=x,  # needed in CustomJS for calculating d
             y_values=y,  # needed in CustomJS for calculating d
            ))
source_im = bokeh.models.ColumnDataSource(data=dict(
             image=[d],  # needed for p.image
             x=[0],  # needed for p.image
             y=[0],  # needed for p.image
             dw = [10],  # needed for p.image
             dh=[10]  # needed for p.image
            ))

p = bokeh.plotting.figure(plot_width=300, plot_height=300,
                          x_range=[0, 10], y_range=[0, 10])
im = p.image(source=source_im, palette="Spectral11")

slider_callback = bokeh.models.CustomJS(args=dict(
                source=source,source_im=source_im), code="""
        var x = source.data['x_values'];
        var y = source.data['y_values'];
        var d = source_im.data['image'][0];
        var f = slider.value;
        for (var j = 0; j < y.length; j++){
            for (var i = 0; i < x.length; i++) {
                d[j*y.length + i] = Math.sin(f * x[i]) * Math.cos(f * y[j]);
            }
        }
        source_im.change.emit();
    """)

slider = bokeh.models.Slider(start=0.1, end=4, value=1, step=.1,
                             title="angular frequency")
slider.js_on_change('value', slider_callback)
slider_callback.args['slider'] = slider
layout = bokeh.models.layouts.Row(p,slider)

bokeh.io.output_notebook()
bokeh.io.show(layout)

关于javascript - Bokeh :在图像图中实现自定义 javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33789011/

有关javascript - Bokeh :在图像图中实现自定义 javascript的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  4. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  5. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  6. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  7. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  8. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  9. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  10. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

随机推荐