在散景中显示裁剪的图像

时间:2018-07-27 22:32:39

标签: javascript python user-interface bokeh

我正在以散景的形式在图中显示图片,并使用BoxSelectTool绘制矩形。

data

现在,我想在绘制矩形之后,不单击按钮或其他任何东西,以不同的较小图形显示该图像区域:

<template>
    <p>Resize me! Current width is: {{ windowWidth }}</p>
</template

<script>
    export default {
        data() {
            return {
                windowWidth: window.innerWidth
            }
        },
        mounted() {
            window.onresize = () => {
                this.windowWidth = window.innerWidth
            }
        }
    }
</script>

所以我在JS中需要这样的东西:

box_select = BoxSelectTool(callback=callback)

p2 = figure(x_range=(0,700), y_range=(0,500),plot_width=1100,plot_height=1100,tools=[box_select])
p2.image_url( url='url',
         x=1, y=1, w=700, h=500, anchor="bottom_left",source=im_src)

rect_source = ColumnDataSource(data=dict(x=[], y=[], width=[], height=[]))
callback = CustomJS(args=dict(rect_source=rect_source), code="""
    // get data source from Callback args
    var data = rect_source.data;

    /// get BoxSelectTool dimensions from cb_data parameter of Callback
    var geometry = cb_data['geometry'];

    /// calculate Rect attributes
    var width = geometry['x1'] - geometry['x0'];
    var height = geometry['y1'] - geometry['y0'];
    var x = geometry['x0'] + width/2;
    var y = geometry['y0'] + height/2;

    /// update data source with new Rect attributes
    data['x'].push(x);
    data['y'].push(y);
    data['width'].push(width);
    data['height'].push(height);

    rect_source.data = data;
    rect_source.change.emit();
'''

如何在JS + bokeh中做到这一点?

1 个答案:

答案 0 :(得分:1)

我建议使用模块holoviews(pyviz生态系统的一部分)执行此任务,该模块可提供对bokeh的高级访问。

Holoviews提供了所谓的streams,可以与DynamicMaps一起使用,以基于流的(不断变化的)值生成动态图形。

panel模块(也是pyviz生态系统的一部分)可用于定义可视化的布局。

import numpy as np
import holoviews as hv
from holoviews import opts
from holoviews.streams import BoundsXY
import panel as pn

pn.extension() # loading the panel extension for use with notebook
opts.defaults(opts.Image(tools=['box_select'])) # making sure, that box_select is available

minval, maxval = 0, 200

# x-y data
ls = np.linspace(minval, 10, maxval)
xx, yy = np.meshgrid(ls, ls)
# z-data, e.g. intensity
zz = xx*yy

# min and max, later used to recalibrate the colormapping
zzmin = zz.min()
zzmax = zz.max() 

bounds=(0,0, 1,1) # bounds used for the image
im = hv.Image(zz, bounds=bounds)

# stream, xy-data are provided by the box_select-tool
# As start values the same bounds as for the image are used.
box = BoundsXY(bounds=bounds) 

# The box-stream is used to draw a rectangle dynamically
# based on the current selection using the box_select-tool.
rect = hv.DynamicMap(
    lambda bounds: hv.Bounds(bounds),
    streams=[box])

# The box-stream is used to draw an image dynamically
# based on the current selection using the box_select-tool.
im_select = hv.DynamicMap(
    lambda bounds: im[bounds[0]:bounds[2],bounds[1]:bounds[3]],
    streams=[box])

# Arranging the layout.
# With redim.range we make sure the colormapping uses the original min- and max-values as in 'im',
# and not the min- and max-values from 'im_select'.
layout = pn.Row(im * rect \
                +\
                im_select.redim.range(z=(zzmin, zzmax))) 
layout.app()

enter image description here