渲染器不更新 bokehjs 中绘图上的字形
Renderer not updating glyph on plot in bokehjs
更新 25-09-2018
为了针对这个问题创建一个更简单的演示(在此发布:http://jsfiddle.net/bLgj4vc7/3/),我终于找到了问题的根本原因。我也设法解决了这个问题,我已将其作为答案发布。
我在我的网络应用程序中使用独立的 bokehjs。我的问题是渲染器没有使用更新的数据源更新其行字形(或者至少这就是我看来的问题)。
这个 jsfiddle: http://jsfiddle.net/uwnqcotg/8/ 演示了这个问题。请忽略其中任何错误的编码约定;这是一个快速的一次性演示。
在 fiddle 中,该图加载了一个数据系列,该数据系列呈现得非常漂亮。该图可以通过两种方式更新:
Update Plot Once By Overwriting CDS.data Object
一次性覆盖 ColumnDataSource.data 对象,从而遵循保持相同列长度的散景原则。
Start Stream With CDS.stream
使用 ColumnDataSource.stream() 并使用随机生成的增量数据系列定期更新绘图。
在第一种方法中,字形似乎正在更新 - 轴确实根据控制台中打印的数据系列进行了更新以供参考。但是,绘制的字形和数据系列显示不匹配。对我来说,它看起来像是在绘图初始化时绘制的字形只是重新调整到新轴,虽然我不能确定。
在第二种方法中,同样更新了坐标轴,但没有更新字形。同样,最初绘制的字形似乎重新调整到新的轴范围。此外,rollover
属性似乎被忽略了,因为渲染器只是不断积累数据。
总的来说,我的观察是在渲染器初始化期间提供给渲染器的任何数据都被正确绘制,但任何后续的流式更新甚至覆盖都没有。虽然我在这里可能是错的。
另一方面,在我和散景之间,我倾向于相信我做错了什么或者遗漏了什么。那是什么?
正如问题中更新的那样,为了创建一个更简单的演示,在此处发布 http://jsfiddle.net/bLgj4vc7/3/,我 运行 找出了这个问题的根本原因:
看起来 bokehjs 有一个错误,其中渲染器一旦用一定长度的数据集初始化,即使在数据集的后续更新中也会坚持该长度。也就是说,
- 如果渲染器是使用空数据集
{x:[], y:[]}
初始化的,即使稍后使用填充的数据集更新 renderer.data_source,渲染器也会保持零长度并且不会在剧情.
- 对于长度为 5 的初始数据集,只会从任何后续更新中读取前 5 个点,并且相应地更新字形。其余点不承认。
我不知道问题是渲染器没有读取超过初始长度,还是读取了但未能在绘图上重绘字形。 ColumnDataSource
肯定更新正确。
此答案中链接的 fiddle 最能说明问题。
那么解决方法是什么?目前,此解决方法:使用填充 NaN
s 的数据集初始化渲染器,其长度等于或大于您要为单个数据系列绘制的最大数据点数。
所以,如果在一行字形中,我希望绘制最多 100 个数据点,那么:
const plot = Bokeh.Plotting.figure()
const maxDataPoints = 100 // maximum number of points I want for this glyph
const emptyData = Array().fill().map(_ => NaN)
const cds = new Bokeh.ColumnDataSource({x: emptyData, y: emptyData})
const renderer = plot.line({field: 'x'}, {field: 'y'}, {source: cds, line_width: 2})
// now any subsequent updates to datasource of renderer will update its glyph on the plot.
renderer.data_source.data = {
x: dataLengthLessOrEqualToMaxDataPoints.x,
y: dataLengthLessOrEqualToMaxDataPoints.y
}
当然,我认为 bokehjs 的这种行为要么是一个错误,要么是我在初始化中遗漏了一个未记录的步骤。无论哪种方式,都值得在 github 上创建一个问题:https://github.com/bokeh/bokeh/issues/8277
更新 25-09-2018
为了针对这个问题创建一个更简单的演示(在此发布:http://jsfiddle.net/bLgj4vc7/3/),我终于找到了问题的根本原因。我也设法解决了这个问题,我已将其作为答案发布。
我在我的网络应用程序中使用独立的 bokehjs。我的问题是渲染器没有使用更新的数据源更新其行字形(或者至少这就是我看来的问题)。
这个 jsfiddle: http://jsfiddle.net/uwnqcotg/8/ 演示了这个问题。请忽略其中任何错误的编码约定;这是一个快速的一次性演示。
在 fiddle 中,该图加载了一个数据系列,该数据系列呈现得非常漂亮。该图可以通过两种方式更新:
Update Plot Once By Overwriting CDS.data Object
一次性覆盖 ColumnDataSource.data 对象,从而遵循保持相同列长度的散景原则。Start Stream With CDS.stream
使用 ColumnDataSource.stream() 并使用随机生成的增量数据系列定期更新绘图。
在第一种方法中,字形似乎正在更新 - 轴确实根据控制台中打印的数据系列进行了更新以供参考。但是,绘制的字形和数据系列显示不匹配。对我来说,它看起来像是在绘图初始化时绘制的字形只是重新调整到新轴,虽然我不能确定。
在第二种方法中,同样更新了坐标轴,但没有更新字形。同样,最初绘制的字形似乎重新调整到新的轴范围。此外,rollover
属性似乎被忽略了,因为渲染器只是不断积累数据。
总的来说,我的观察是在渲染器初始化期间提供给渲染器的任何数据都被正确绘制,但任何后续的流式更新甚至覆盖都没有。虽然我在这里可能是错的。
另一方面,在我和散景之间,我倾向于相信我做错了什么或者遗漏了什么。那是什么?
正如问题中更新的那样,为了创建一个更简单的演示,在此处发布 http://jsfiddle.net/bLgj4vc7/3/,我 运行 找出了这个问题的根本原因:
看起来 bokehjs 有一个错误,其中渲染器一旦用一定长度的数据集初始化,即使在数据集的后续更新中也会坚持该长度。也就是说,
- 如果渲染器是使用空数据集
{x:[], y:[]}
初始化的,即使稍后使用填充的数据集更新 renderer.data_source,渲染器也会保持零长度并且不会在剧情. - 对于长度为 5 的初始数据集,只会从任何后续更新中读取前 5 个点,并且相应地更新字形。其余点不承认。
我不知道问题是渲染器没有读取超过初始长度,还是读取了但未能在绘图上重绘字形。 ColumnDataSource
肯定更新正确。
此答案中链接的 fiddle 最能说明问题。
那么解决方法是什么?目前,此解决方法:使用填充 NaN
s 的数据集初始化渲染器,其长度等于或大于您要为单个数据系列绘制的最大数据点数。
所以,如果在一行字形中,我希望绘制最多 100 个数据点,那么:
const plot = Bokeh.Plotting.figure()
const maxDataPoints = 100 // maximum number of points I want for this glyph
const emptyData = Array().fill().map(_ => NaN)
const cds = new Bokeh.ColumnDataSource({x: emptyData, y: emptyData})
const renderer = plot.line({field: 'x'}, {field: 'y'}, {source: cds, line_width: 2})
// now any subsequent updates to datasource of renderer will update its glyph on the plot.
renderer.data_source.data = {
x: dataLengthLessOrEqualToMaxDataPoints.x,
y: dataLengthLessOrEqualToMaxDataPoints.y
}
当然,我认为 bokehjs 的这种行为要么是一个错误,要么是我在初始化中遗漏了一个未记录的步骤。无论哪种方式,都值得在 github 上创建一个问题:https://github.com/bokeh/bokeh/issues/8277