散景:在图像字形上启用悬停工具

时间:2017-02-19 23:35:55

标签: bokeh

是否可以在图像上启用悬停工具(由image()image_rgba()image_url()创建的字形),以便在将鼠标悬停在点上时显示一些上下文数据图片。在文档中,我发现只有线条或标记等字形的悬停工具的参考和示例。

可能的解决方法解决方案:

我认为可以将2d信号数据转换为具有x,y和值列的柱状Dataframe格式。并使用rect字形而不是图像。但这也需要正确处理颜色映射。特别是,当值是实数而不是可以传递给某些调色板的整数时处理这种情况。

3 个答案:

答案 0 :(得分:1)

好的,在深入研究文档和示例之后,我可能会自己回答这个问题。

悬浮对图像(2d信号)数据的影响对于如何在Bokeh中设计此功能没有任何意义。如果需要添加一些附加到数据点的额外信息,则需要将数据放入适当的数据模型 - 平面数据模型。

整理数据

基本上,需要将他的数据整理成带有x,y和value列的表格格式(参见Tidy Data article by H.Wickham)。现在每行代表一个数据点,人们可以自然地将任何上下文信息添加为附加列。

例如,以下代码将完成工作:

def flatten(matrix: np.ndarray,
            extent: Optional[Tuple[float, float, float, float]] = None,
            round_digits: Optional[int] = 0) -> pd.DataFrame:

    if extent is None:
        extent = (0, matrix.shape[1], 0, matrix.shape[0])

    x_min, x_max, y_min, y_max = extent

    df = pd.DataFrame(data=matrix)\
        .stack()\
        .reset_index()\
        .rename(columns={'level_0': 'y', 'level_1': 'x', 0: 'value'})

    df.x = df.x / df.x.max() * (x_max - x_min) + x_min
    df.y = df.y / df.y.max() * (y_max - y_min) + y_min

    if round_digits is not None:
        df = df.round({'x': round_digits, 'y': round_digits})

    return df

rect字形和ColumnDataSource

然后,使用rect字形代替image,相应地映射x,y,并将值列正确地映射到字形的颜色美学。

值的颜色映射

  • 在这里你可以使用min-max标准化,然后乘以你想要使用的颜色数和round
  • 使用bokeh builtin palettes将计算的整数值映射到特定的颜色值。

总而言之,这是一个示例图表函数:

def InteractiveImage(img: pd.DataFrame,
          x: str,
          y: str,
          value: str,
          width: Optional[int] = None,
          height: Optional[int] = None,
          color_pallete: Optional[List[str]] = None,
          tooltips: Optional[List[Tuple[str]]] = None) -> Figure:
    """

    Notes
    -----
        both x and y should be sampled with a constant rate
    Parameters
    ----------
    img
    x
        Column name to map on x axis coordinates
    y
        Column name to map on y axis coordinates 
    value
        Column name to map color on
    width
        Image width
    height
        Image height
    color_pallete
        Optional. Color map to use for values
    tooltips
        Optional.
    Returns
    -------
        bokeh figure
    """

    if tooltips is None:
        tooltips = [
            (value, '@' + value),
            (x, '@' + x),
            (y, '@' + y)
        ]

    if color_pallete is None:
        color_pallete = bokeh.palettes.viridis(50)

    x_min, x_max = img[x].min(), img[x].max()
    y_min, y_max = img[y].min(), img[y].max()

    if width is None:
        width = 500 if height is None else int(round((x_max - x_min) / (y_max - y_min) * height))
    if height is None:
        height = int(round((y_max - y_min) / (x_max - x_min) * width))

    img['color'] = (img[value] - img[value].min()) / (img[value].max() - img[value].min()) * (len(color_pallete) - 1)
    img['color'] = img['color'].round().map(lambda x: color_pallete[int(x)])

    source = ColumnDataSource(data={col: img[col] for col in img.columns})

    fig = figure(width=width,
                 height=height,
                 x_range=(x_min, x_max),
                 y_range=(y_min, y_max),
                 tools='pan,wheel_zoom,box_zoom,reset,hover,save')

    def sampling_period(values: pd.Series) -> float:
        # @TODO think about more clever way
        return next(filter(lambda x: not pd.isnull(x) and 0 < x, values.diff().round(2).unique()))

    x_unit = sampling_period(img[x])
    y_unit = sampling_period(img[y])

    fig.rect(x=x, y=y, width=x_unit, height=y_unit, color='color', line_color='color', source=source)
    fig.select_one(HoverTool).tooltips = tooltips

    return fig

####注意:但是这需要相当高的计算价格

答案 1 :(得分:1)

基于Alexander Reshytko的上述自我回答,我已经实现了一个大多数已经准备好下架的版本,并举了一些例子。修改它以适应您自己的应用程序应该更直接,并且不依赖于我真正使用或理解的Pandas数据帧。 Github: Bokeh - Image with HoverTool

上的代码和示例

答案 2 :(得分:1)

散景版0.12.16的更新

Bokeh版本0.12.16支持HoverTool image的{​​{1}}。看到: bokeh release 0.12.16

用于错误的散景版本:

以下是我使用glyphs将鼠标悬停在图片上并在其顶部添加一个隐藏(bokeh.plotting.imagealpha=0并具有悬停功能的方法数据坐标。我将它用于大约1500行和40000列的图像。

bokeh.plotting.quad

此处显示了选择{0}的最小值和最大值的功能的完整示例和图像:Utilities for interactive scientific plots using python, bokeh and javascript. 更新:最新散景已经支持# This is used for hover and taptool imquad = p.quad(top=[y1], bottom=[y0], left=[x0], right=[x1],alpha=0) color_mapper个调色板,但是当我创建此代码时,我需要从matplotlib生成它们

在显示的示例中,我决定不在cmap函数中使用matplotlib.cm.get_cmap在图像上显示工具提示。相反,我将它们显示在单独的tooltips=None字形中。