是否可以从交互式散景图生成计算出的图/数据?

问题描述 投票:0回答:1

我有一个图,其中有一些固定的理论点,并且使用多选按钮的组合来绘制实验点。有什么方法可以生成理论点和实验数据之间的%误差数据?

该图的示例如下所示:

Example plot

python-3.x plot bokeh interactive
1个回答
0
投票

此代码在理论点旁边以文本形式显示百分比误差。您还可以在画布上从理论点到实验点画一条线,差异数据将显示在工具提示中。第一次单击(释放按钮)将启动“差异”行。再次单击将结束它。工具提示始终保留在图上,但您可以轻松对其进行调整,使其在第二次单击后消失。

import numpy as np
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.events import *

source = ColumnDataSource({'x': [], 'y': []})

p = figure(plot_width = 900)

x_data = np.arange(10)
source_expected = dict(x = x_data, y = np.random.random(10), color=['blue']*10)
source_measured = dict(x = x_data, y = np.random.random(10), color=['grey']*10)

line_expected = p.line('x', 'y', line_color = 'blue', source = source_expected)
circle_expected = p.circle('x', 'y', color = 'color', source = source_expected, size = 10)

line_measured = p.line('x', 'y', line_color = 'grey', source = source_measured)

# circle_measured = p.circle('x', 'y', color = 'color', fill_color = 'white', source = source_measured, size = 60)
circle_measured = p.circle('x', 'y', color = 'color', source = source_measured, size = 10)

source_error = {'x': [], 'y': [], 'error': [], 'percent': [], 'text': [], 'color': []}

i = 0
for expected, measured in zip(source_expected['y'], source_measured['y']):
    source_error['x'].append(x_data[i])
    source_error['y'].append(measured)

    error = expected - measured
    percent = (error/expected) * 100

    source_error['error'].append(error)
    source_error['percent'].append(percent)
    source_error['text'].append('+{}%'.format('%.2f' % percent) if percent > 0 else '{}%'.format('%.2f' % percent))
    source_error['color'].append('green' if expected == measured else 'red')

    i = i + 1

# text_measured = p.text('x', 'y', text = 'text', text_color = 'color', text_font_size = '9pt', x_offset = -25, y_offset = 6, source = source_error)    
text_measured = p.text('x', 'y', text = 'text', text_color = 'color', text_font_size = '9pt', x_offset = 10, y_offset = 5, source = source_error)


line = p.line('x', 'y', line_color = 'red', line_dash = 'dashed', source = source)

callback_tap = '''

if (typeof custom_tooltip == 'undefined') {
        custom_tooltip = document.createElement('div');
        custom_tooltip.setAttribute('id','tooltip_div');
        custom_tooltip.style = 'position: absolute; left: 0px; top: 0px; z-index: 9999; border:1px solid black; padding: 10px; background: white; font-family: arial; font-size: 12px'
        document.body.prepend(custom_tooltip);  
}        

if (true === Bokeh.drawing) {
    Bokeh.drawing = false
}
else {
    if (!Bokeh.drawing) {
        src.data = {'x':[], 'y':[]}        
        src.change.emit()
    }

    src.data['x'].push(cb_obj.x)
    src.data['y'].push(cb_obj.y)

    Bokeh.drawing = true
    Bokeh.sx_start = cb_obj.sx
    Bokeh.x_start = cb_obj.x
    Bokeh.sy_start = cb_obj.sy
    Bokeh.y_start = cb_obj.y  
}'''

callback_mousemove = '''
function print(...args) {
    for (i in args) {
        console.log(args[i])
    }
}

if (Bokeh.drawing) {  
    if (src.data['x'].length > 1) {
        src.data['x'].pop()
        src.data['y'].pop()   
    }

    src.data['x'].push(cb_obj.x)
    src.data['y'].push(cb_obj.y)
    src.change.emit()

    tooltip = document.getElementById('tooltip_div')
    tooltip.style.left = cb_obj.sx + 30 + 'px'
    tooltip.style.top = cb_obj.sy + 10 + 'px'
    var error = Math.round((Bokeh.y_start - cb_obj.y) * 100) / 100
    var percent = Math.round(error * 100 / Bokeh.y_start) 
    tooltip.innerHTML = 'Distance X: ' + Math.round(Bokeh.sx_start - cb_obj.sx) + ' px' + ' (' + (Math.round((Bokeh.x_start - cb_obj.x) * 100) / 100) + ' units)' + 
                        '<br />' +
                        'Distance Y: ' + Math.round(Bokeh.sy_start - cb_obj.sy) + ' px' + ' (' + (Math.round((Bokeh.y_start - cb_obj.y) * 100) / 100) + ' units)' + 
                        '<br />' +
                        'Error: ' + error + ' units' + 
                        '<br />' +
                        '% Error: ' + percent + ' %'
}'''

p.js_on_event('tap', CustomJS(args = {'src': source, }, code = callback_tap))
p.js_on_event('mousemove', CustomJS(args = {'src': source, }, code = callback_mousemove))

show(p)

结果:

enter image description here

将注释的行与旁边的行交换会使错误百分比显示在代表理论点的大圆圈中。看起来像这样:

enter image description here

此脚本是为Python v3.7.2Bokeh v1.3.0]编写的>

© www.soinside.com 2019 - 2024. All rights reserved.