4

我使用散景来绘制温度曲线,但在某些情况下,数据集非常大(> 500k 测量值),并且我对散景的用户体验滞后(事件与 output_backend="webgl")。所以我正在试验数据着色器以获得更快的渲染和更流畅的用户体验。

但是datashader给出的视觉效果不如bokeh的结果漂亮,datashader的结果有锯齿:

在此处输入图像描述

我获得了与以下代码的并排比较:

import pandas as pd
import datashader as ds
import datashader.transfer_functions as tf
from bokeh.plotting import figure
from bokeh.io import output_notebook, show
from bokeh.models import ColumnDataSource
from bokeh.layouts import row
import numpy as np

output_notebook()

# generate signal
n = 2000
start = 0
end = 70
signal = [np.sin(x) for x in np.arange(start, end, step=(end-start)/n)]
signal = pd.DataFrame(signal, columns=["signal"])
signal = signal.reset_index()

# create a bokeh plot
source = ColumnDataSource(signal)
p = figure(plot_height=300, plot_width=400, title="bokeh plot")
p.line(source=source, x="index", y="signal")

# create a datashader image and put it in a bokeh plot
x_range = (signal["index"].min(), signal["index"].max())
y_range = (signal["signal"].min(), signal["signal"].max())
cvs = ds.Canvas(x_range=x_range, y_range=y_range, plot_height=300, plot_width=400)
agg = cvs.line(signal, 'index', 'signal')
img = tf.shade(agg)
image_source = ColumnDataSource(data=dict(image = [img.data]))
q = figure(x_range=x_range, y_range=y_range, plot_height=300, plot_width=400, title="datashader + bokeh")
q.image_rgba(source = image_source,
             image="image",
             dh=(y_range[1] - y_range[0]),
             dw=(x_range[1] - x_range[0]),
             x=x_range[0],
             y=y_range[0],
             dilate=False)

# visualize both plot, bokeh on left
show(row(p, q))

您知道如何修复这种混叠并获得平滑的结果吗?(类似于散景的结果)

4

1 回答 1

5

这是您的代码的可运行版本,在 Jupyter 笔记本中使用 HoloViews:

import pandas as pd, numpy as np, holoviews as hv
from holoviews.operation.datashader import datashade, dynspread
hv.extension("bokeh")
%opts Curve RGB [width=400]
n, start, end = 2000, 0, 70
sine = [np.sin(x) for x in np.arange(start, end, step=(end-start)/n)]
signal = pd.DataFrame(sine, columns=["signal"]).reset_index()
curve = hv.Curve(signal)

curve + datashade(curve)

前

确实,这里的数据阴影输出看起来不太好。Datashader 的时间序列支持,与 datashader 的其余部分一样,旨在允许在栅格网格上准确累积和求和大量数学上完美(即无限细)的曲线,因此每条曲线上的每个 x 位置都将落入一个且唯一网格中的一个 y 位置。在这里,您似乎只是想要大型时间序列的服务器端渲染,这需要对网格中多个附近的 bin 进行部分递增,并且尚未优化 datashader。

您已经可以做的一件事是以高分辨率渲染曲线,然后“传播”它,以便每个非零像素也将显示在相邻像素中:

curve + dynspread(datashade(curve, height=1200, width=1200, dynamic=False, \
                            cmap=["#30a2da"]), max_px=3, threshold=1)

传播

在这里,我将颜色设置为与 Bokeh 的默认值相匹配,然后强制 HoloView 的“dynspread”函数传播 3 个像素。在您的版本中使用 Datashader+Bokeh,您将执行“img = tf.spread(tf.shade(agg), px=3)”并增加 Canvas 调用中的绘图大小以获得类似的结果。

我没有尝试在 tf.shade() 或 tf.spread() 的结果上运行一个简单的平滑过滤器,但它们都只返回 RGB 图像,所以像这样的一些过滤器可能会产生良好的结果。

真正的解决方案是为 datashader 实现一个可选的抗锯齿线条绘制功能,在首先绘制线条时操作,而不是稍后修复像素,但这需要一些工作。欢迎投稿!

于 2018-01-15T19:05:20.690 回答