简体   繁体   English

如何使用Bokeh(或其他库)在python中制作轮廓图?

[英]How to make a contour plot in python using Bokeh (or other libs)?

I am interested in making a contour plot in Bokeh. 我有兴趣在Bokeh制作等高线图。 I have not been able to find anything on the net so far. 到目前为止,我还没能在网上找到任何东西。

As a reminder, this is contour plot: 提醒一下,这是轮廓图:

在此输入图像描述

Any help would be appreciated. 任何帮助,将不胜感激。 I would also welcome suggestions to other libraries but with prerequisite of allowing for interactive/animated plots, and not only rendering static output (images). 我也欢迎其他图书馆的建议,但前提条件是允许交互式/动画图,而不仅仅是渲染静态输出(图像)。

You can also use matplotlibs contour plot for calculation of the contour data and then plot the contours using bokehs multi_line. 您还可以使用matplotlibs等高线图来计算轮廓数据,然后使用散景multi_line绘制轮廓。 I'm also plotting text labels (which are unfortunately a bit ugly). 我也在绘制文字标签(不幸的是有点难看)。

import numpy as np
import matplotlib.pyplot as plt
from bokeh.models import ColumnDataSource
from bokeh.io import output_file
from bokeh.plotting import gridplot,figure, show

def get_contour_data(X, Y, Z):
    cs = plt.contour(X, Y, Z)
    xs = []
    ys = []
    xt = []
    yt = []
    col = []
    text = []
    isolevelid = 0
    for isolevel in cs.collections:
        isocol = isolevel.get_color()[0]
        thecol = 3 * [None]
        theiso = str(cs.get_array()[isolevelid])
        isolevelid += 1
        for i in range(3):
            thecol[i] = int(255 * isocol[i])
        thecol = '#%02x%02x%02x' % (thecol[0], thecol[1], thecol[2])

        for path in isolevel.get_paths():
            v = path.vertices
            x = v[:, 0]
            y = v[:, 1]
            xs.append(x.tolist())
            ys.append(y.tolist())
            xt.append(x[len(x) / 2])
            yt.append(y[len(y) / 2])
            text.append(theiso)
            col.append(thecol)

    source = ColumnDataSource(data={'xs': xs, 'ys': ys, 'line_color': col,'xt':xt,'yt':yt,'text':text})
    return source


output_file("contour.html")

N = 400
x = np.linspace(-1, 1, N)
y = np.linspace(-1, 1, N)
X, Y = np.meshgrid(x, y)
Z = X**2 + Y**2

source = get_contour_data(X,Y,Z)
plot = figure(plot_width=400,plot_height=400,x_range=[-1,1], y_range=[-1,1])
plot.multi_line(xs='xs', ys='ys', line_color='line_color', source=source)
plot.text(x='xt',y='yt',text='text',source=source,text_baseline='middle',text_align='center')
show(plot)

this is the output: 这是输出:

在此输入图像描述

I wrote a filled contour tool based on matplotlib output: 我写了一个基于matplotlib输出的填充轮廓工具:

https://github.com/asher-pembroke/bokeh-tools https://github.com/asher-pembroke/bokeh-tools

Plotly has supported contour plots in Python for the past year: Plotly过去一年在Python中支持等高线图:

https://plot.ly/python/contour-plots/ https://plot.ly/python/contour-plots/

https://plot.ly/pandas/contour-plots/ https://plot.ly/pandas/contour-plots/

Density plots (contour plots with adjacent histograms): 密度图(具有相邻直方图的等高线图):

https://plot.ly/python/2d-density-plots/ https://plot.ly/python/2d-density-plots/

https://plot.ly/pandas/2d-density-plots/ https://plot.ly/pandas/2d-density-plots/

The Plotly Python library is on pip, 100% free and open-source. Plotly Python库是pip,100%免费和开源。

蟒蛇轮廓积

By choosing a palette with 10 values, like in the example you provide, one can use image (see Bokeh image example ) in bokeh to simulate a contour plot. 通过选择具有10个值的调色板(如您提供的示例),可以使用散景图像 (请参见散景图像示例 )来模拟等高线图。 The black contour lines and the numbers are missing, but the boundaries between the colors are actually the contour lines. 黑色轮廓线和数字缺失,但颜色之间的边界实际上是轮廓线。 Also, as far as I know Bokeh does not provide a color bar, but you can code it as another image (UPDATE: Latests versions of Bokeh do provide colorbar. ) : 此外,据我所知,Bokeh不提供颜色条,但您可以将其编码为另一个图像(更新:Bokeh的Latests版本确实提供了colorbar。)

from bokeh.io import output_file
from bokeh.plotting import gridplot,figure, show
from bokeh.models import ColumnDataSource,FixedTicker
import numpy as np
from matplotlib import cm,colors

output_file("contour.html")
cmap = cm.get_cmap("jet") #choose any matplotlib colormap here
num_slabs = 10 # number of color steps
jet_10 = [colors.rgb2hex(m) for m in cmap(np.arange(0,cmap.N,cmap.N/(num_slabs-1)))]
vmin = 0
vmax = 1550
N = 200
x = np.linspace(0, 10, N)
y = np.linspace(0, 10, N)
xx, yy = np.meshgrid(x, y)
d = vmax * (1. + np.sin(xx)*np.cos(yy))

source = ColumnDataSource(data={'d': [d], 'xx': [x], 'yy': [y]})
p = figure(plot_width=400,plot_height=400,x_range=[0, 10], y_range=[0, 10],min_border_right=10)
p.image(image="d", x=[0], y=[0], dw=[10], dh=[10], palette=jet_10,source=source)

# The following code is for the colorbar:
pcb = figure(plot_width=80,plot_height=400,x_range=[0, 1], y_range=[0, vmax],min_border_right=10)
pcb.image(image=[np.linspace(vmin,vmax,100).reshape(100,1)],x=[0],y=[0],dw=[1],dh=[vmax-vmin], palette=jet_10)
pcb.xaxis.major_label_text_color = None
pcb.xaxis.major_tick_line_color = None
pcb.xaxis.minor_tick_line_color = None
pcb.yaxis[0].ticker=FixedTicker(ticks=np.linspace(vmin,vmax,num_slabs+1)) # 11 ticks
pgrid = gridplot([[p,pcb]])  # this places the colorbar next to the image
show(pgrid)

The output will look like: 输出结果如下: 在此输入图像描述

Thanks Pablo your answer really helped me. 谢谢Pablo你的回答真的帮助了我。

Using your example I made a similar plot that adds the contour lines by using the skimage library. 使用你的例子,我做了一个类似的绘图,通过使用skimage库添加轮廓线。 I also turned on the hover tool as in the Bokeh image example that you referenced. 我也你引用的Bokeh图像示例中那样打开了悬停工具。 Hopefully someone else comes along and adds the line labels. 希望其他人出现并添加行标签。

Note that the following code is meant to run in Jupyter Notebook. 请注意,以下代码旨在在Jupyter Notebook中运行。

from skimage import measure
import numpy as np

from bokeh.plotting import figure, show, output_notebook
from bokeh.models import (ColorBar,
                          FixedTicker, 
                          LinearColorMapper, 
                          PrintfTickFormatter)

output_notebook()

N = 500
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)

mapper = LinearColorMapper(palette='Spectral11', low=-1, high=1)

p = figure(x_range=(0, 10), y_range=(0, 10),
           tooltips=[("x", "$x"), ("y", "$y"), ("value", "@image")])

# must give a vector of image data for image parameter
p.image(image=[d], x=0, y=0, dw=10, dh=10, palette='Spectral11')

levels = np.linspace(-1, 1, 12)
color_bar = ColorBar(color_mapper=mapper, 
                     major_label_text_font_size="8pt",
                     ticker=FixedTicker(ticks=levels),
                     formatter=PrintfTickFormatter(format='%.2f'),
                     label_standoff=6, 
                     border_line_color=None, 
                     location=(0, 0))

p.add_layout(color_bar, 'right')

for level in levels:
  contours = measure.find_contours(d, level)
  for contour in contours:
    x = contour[:,1]/50
    y = contour[:,0]/50
    p.line(x, y, color='grey', line_width=2)

show(p)

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM