等高线图#

等高线图用于计算和渲染二维四边形网格中恒定值的线。线和线之间的填充区域都可以通过单个函数调用来渲染。

简单示例#

这是一个简单的示例,渲染等高线和填充的多边形区域。

import numpy as np

from bokeh.palettes import Sunset8
from bokeh.plotting import figure, show

# Data to contour is the sum of two Gaussian functions.
x, y = np.meshgrid(np.linspace(0, 3, 40), np.linspace(0, 2, 30))
z = 1.3*np.exp(-2.5*((x-1.3)**2 + (y-0.8)**2)) - 1.2*np.exp(-2*((x-1.8)**2 + (y-1.3)**2))

p = figure(width=550, height=300, x_range=(0, 3), y_range=(0, 2))

levels = np.linspace(-1, 1, 9)
contour_renderer = p.contour(x, y, z, levels, fill_color=Sunset8, line_color="black")

colorbar = contour_renderer.construct_color_bar()
p.add_layout(colorbar, "right")

show(p)

按照惯例,z 是要绘制等高线的二维数组,并在 x, y 网格上定义。这里网格是规则间隔的笛卡尔网格。levels 包含要绘制等高线的级别序列。

line_colorfill_color 都是 contour() 的可选关键字参数。line_color 必须指定才能绘制等高线,fill_color 必须指定才能绘制填充的等高线多边形。它们可以是标量或向量视觉属性。

注意

等高线的向量视觉属性的长度为 len(levels),填充的等高线多边形的向量视觉属性的长度为 len(levels)-1

在本例中,line_color 是标量,因此每条等高线都渲染为实心黑线。fill_color 是向量,因此等高线级别之间的填充区域以不同的颜色渲染。

绘图右侧有一个颜色条,它是使用 construct_color_bar() 获得的。它自动显示与等高线图相同的填充和线条视觉属性。

极坐标网格示例#

这是一个更复杂的示例,展示了等高线图的其他可用功能。

import numpy as np

from bokeh.palettes import Cividis
from bokeh.plotting import figure, show

# Data to contour is a 2D sin wave on a polar grid.
radius, angle = np.meshgrid(np.linspace(0, 1, 20), np.linspace(0, 2*np.pi, 120))
x = radius*np.cos(angle)
y = radius*np.sin(angle)
z = 1 + np.sin(3*angle)*np.sin(np.pi*radius)

p = figure(width=550, height=400)

levels = np.linspace(0, 2, 11)

contour_renderer = p.contour(
    x=x, y=y, z=z, levels=levels,
    fill_color=Cividis,
    hatch_pattern=["x"]*5 + [" "]*5,
    hatch_color="white",
    hatch_alpha=0.5,
    line_color=["white"]*5 + ["black"] + ["red"]*5,
    line_dash=["solid"]*6 + ["dashed"]*5,
    line_width=[1]*6 + [2]*5,
)

colorbar = contour_renderer.construct_color_bar(title="Colorbar title")
p.add_layout(colorbar, "right")

show(p)

网格是极坐标的,自身环绕,并且有更多的视觉属性,包括 linefillhatch 属性。其中许多是向量属性,因此可以不同地强调例如正和负等高线级别。

所有视觉属性都可以是标量或正确长度的向量。颜色视觉属性 line_colorfill_colorhatch_color 支持一些额外的指定方式选项

  • 比要求的长度更长或更短的颜色序列将使用 interp_palette() 重新采样。长度为 256 的调色板(例如 Cividis256)在这里很有用。

  • 可以使用调色板集合,例如 Cividis,它是一个字典,将调色板长度(颜色数量)映射到调色板。如果集合包含正确长度的调色板,则使用该调色板。如果所需长度超出集合中可用的长度,则使用最接近长度的调色板,线性插值。

construct_color_bar() 接受传递给 ContourColorBar 构造函数的其他关键字参数,以设置诸如此处显示的 title 等属性。

动画等高线#

Bokeh 可以使用 bokeh serve 生成动画等高线图,因为等高线计算发生在 Python 中。这是一个从 examples/app/contour_animated.py 中提取的示例

import numpy as np

from bokeh.driving import count
from bokeh.palettes import PiYG
from bokeh.plotting import curdoc, figure
from bokeh.plotting.contour import contour_data

x, y = np.meshgrid(np.linspace(-1, 1, 41), np.linspace(-1, 1, 41))
levels = np.linspace(-1.0, 1.0, 11)

def get_z(timestep):
    delta = 0.08*np.cos(timestep*0.15)
    amps  = [0.95, 0.95, -0.95, -0.95]
    xmids = [-0.4,  0.4, -0.4,  0.4]
    ymids = [-0.4,  0.4,  0.4, -0.4]
    rads  = [0.4 + delta, 0.4 + delta, 0.4 - delta, 0.4 - delta]

    z = np.zeros_like(x)
    for amp, xmid, ymid, rad in zip(amps, xmids, ymids, rads):
        z += amp*np.exp( -((x-xmid)**2 + (y-ymid)**2)/rad**2 )
    return z

@count()
def callback(timestep):
    z = get_z(timestep)
    new_contour_data = contour_data(x, y, z, levels)
    contour_renderer.set_data(new_contour_data)

fig = figure(width=600, height=450)

contour_renderer = fig.contour(x, y, get_z(0), levels, fill_color=PiYG,
                               line_color="black", line_width=[1]*5 + [3] + [1]*5)

colorbar = contour_renderer.construct_color_bar()
fig.add_layout(colorbar, 'right')

curdoc().add_periodic_callback(callback, 40)
curdoc().add_root(fig)

要在 Bokeh 服务器上运行此示例,请使用

bokeh serve --show contour_animated.py

执行动画的关键操作顺序是

  1. 像往常一样调用 contour(),并存储返回的 ContourRenderer

  2. 确定更新的 z 数组,它可能从文件读取或计算得出,例如。

  3. 将更新的 z 和未更改的 xylevels 传递给 contour_data() 以生成等高线数据对象。

  4. 使用新的等高线数据对象调用 set_data()

  5. 从阶段 2 重复。

此处的动画示例假定网格、等高线级别和视觉属性未更改。这样做是可能的,但需要小心正确处理变化的绘图边界以及视觉属性到等高线级别的分配,因此在这些情况下,通常更容易删除旧的、不需要的等高线图,并用新的等高线图替换它。

高级细节#

contour() 唯一强制性的关键字参数是 zlevelsfill_colorline_color 中的至少一个。xy 是可选的,如果未指定,则将使用笛卡尔网格,在两个方向上的网格间距为 1。

要从等高线计算中排除网格点,则对 z 使用 NumPy 掩码数组,并排除掩盖的网格点,或者将这些网格点的 z 值设置为 np.nan

等高线使用 MultiLine 字形实现,填充的等高线多边形使用 MultiPolygons 字形实现,并将 line_width 设置为零。

等高线的计算由 ContourPy 执行。有关此信息,请参阅 ContourPy 文档

注意

等高线是在 Bokeh 3.0 版本中添加的,计划在未来的版本中进行改进。