You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 10:28:02