求助:Bokeh脚本运行后浏览器中月度合成海表温度(SST)无变化的问题
求助:Bokeh脚本运行后浏览器中月度合成海表温度(SST)无变化的问题
嘿,我帮你揪出问题啦!你的代码逻辑其实没问题,月度SST数据确实是不同的,但CustomJS里更新数据源的方式不对,导致Bokeh没察觉到数据变化,所以浏览器里的图表一直没更新。
问题根源
你用Object.assign重新赋值了整个source.data对象,但这种操作不会触发Bokeh的视图更新机制。Bokeh的ColumnDataSource需要明确的信号才能知道“数据变了,该重绘图表了”。
解决方法
把回调里更新数据源的代码改成直接修改现有数组元素+手动触发更新信号,具体改法如下:
把原来的这段JS代码:
source.data = Object.assign({}, source.data, {image: [frames[current]]});
替换成:
// 直接修改image数组的第一个元素 source.data.image[0] = frames[current]; // 手动触发数据源变化通知,让图表重绘 source.change.emit();
修改后的完整脚本
这里给你贴出修复后的完整代码,直接运行就能看到动画效果了:
import numpy as np from bokeh.io import output_file, show from bokeh.plotting import figure from bokeh.models import ( ColumnDataSource, LinearColorMapper, ColorBar, Button, CustomJS, Title ) from bokeh.layouts import column # Grid lon = np.linspace(-180, 180, 18) lat = np.linspace(-90, 90, 9) lon2d, lat2d = np.meshgrid(lon, lat) # Generate 12 months of SST data with clear variability frames = [] for month in range(12): sst = ( 15 + 10 * np.cos(lat2d * np.pi / 18) + 10 * np.sin((lon2d + month * 30) * np.pi / 9) + 5 * np.cos(lat2d * np.pi / 45 + month) + np.random.normal(scale=1.5, size=lat2d.shape) ) frames.append(sst) # Color scaling vmin = np.min(frames) vmax = np.max(frames) mapper = LinearColorMapper(palette="Turbo256", low=vmin, high=vmax) # Initial frame source = ColumnDataSource(data=dict(image=[frames[0]])) # Figure p = figure( x_range=(-180, 180), y_range=(-90, 90), width=800, height=400 ) p.image( image="image", x=-180, y=-90, dw=360, dh=180, color_mapper=mapper, source=source ) color_bar = ColorBar(color_mapper=mapper) p.add_layout(color_bar, 'right') # Title title = Title(text="Monthly SST - Jan") p.add_layout(title, 'above') # Button button = Button(label="▶ Play", width=100) # Convert frames to nested lists for JavaScript frames_list = [f.tolist() for f in frames] # Callback: escape all braces carefully callback = CustomJS(args=dict(source=source, button=button, title=title), code=f""" if (!window._sst_anim) {{ var frames = {frames_list}; var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; var current = 0; window._sst_anim = setInterval(function() {{ current = (current + 1) % frames.length; // 修改这里:直接更新数组元素并触发变化 source.data.image[0] = frames[current]; source.change.emit(); title.text = "Monthly SST - " + months[current]; }}, 600); button.label = "⏸ Pause"; }} else {{ clearInterval(window._sst_anim); window._sst_anim = null; button.label = "▶ Play"; }} """) button.js_on_click(callback) # Output output_file("sst_animation_working.html") show(column(button, p))
现在运行这个脚本,点击Play按钮就能看到月度SST的动态变化啦,标题也会同步切换月份~
内容来源于stack exchange
相关产品推荐
相关产品推荐

