散景 selected.on_change 不适用于我当前的设置

bokeh selected.on_change not working for my current setup

基本上,这是一个交互式热图,但不同之处在于源是通过从定期更新的文件中读取值来更新的。

不要理会 class "generator",它只是为了保存数据,它 运行 定期线程化

在执行散景脚本之前,请确保在脚本的同一目录中存在名为 "Server_dump.txt" 的文件,其中的单个数字大于 0。

基本上发生的事情是我通过在 bash 上使用 echo 4 > Server_dump.txt 来更改名为 "Server_dump.txt" 的文件中的一个数字, 你可以输入 4 以外的任何数字,脚本会自动检查文件并绘制新点。

如果你不使用bash,你可以使用文本编辑器,替换数字并保存,一切都是一样的。

生成器中的 运行 函数 class 是检查此文件是否被修改、读取数字、将其转换为 x& y 坐标并增加与这些关联的抽头数的函数坐标并根据该数字给出 source x,y,taps 值。

好吧,这个函数工作正常,每次我回显一个数字,都会绘制出正确的矩形,但是,

*如果我通过多次将数字写入文件来增加某个矩形的 self.taps,颜色会更新,但如果我将鼠标悬停在矩形上,它会显示过去的值而不是最新值.

我的散景版本是 1.0.4

from functools import partial
from random import random,randint
import threading 
import time
from tornado import gen
from os.path import getmtime
from math import pi
import pandas as pd
from random import randint, random
from bokeh.io import show
from bokeh.models import LinearColorMapper, BasicTicker, widgets, PrintfTickFormatter, ColorBar, ColumnDataSource, FactorRange
from bokeh.plotting import figure, curdoc
from bokeh.layouts import row, column, gridplot

source = ColumnDataSource(data=dict(x=[], y=[], taps=[]))

doc = curdoc()

#sloppy data receiving function to change data to a plottable shape 
class generator(threading.Thread):
    def __init__(self):
        super(generator, self).__init__()
        self.chart_coords = {'x':[],'y':[],'taps':[]}
        self.Pi_coords = {}  
        self.coord = 0
        self.pos = 0
        self.col = 0
        self.row = 0
        self.s = 0
        self.t = 0

    def chart_dict_gen(self,row, col):
        self.col = col
        self.row = row+1
        self.chart_coords['x'] = [i for i in range(1,cla.row)]
        self.chart_coords['y'] = [i for i in range(cla.col, 0, -1)] #reversed list because chart requires that
        self.chart_coords['taps']= [0]*(row * col)
        self.taps = [[0 for y in range(col)] for x in range(row)]

    def Pi_dict_gen(self,row,col):
        key = 1
       for x in range(1,row):
           for y in range(1,col):
               self.Pi_coords[key] = (x,y)
               key = key + 1

    def Pi_to_chart(self,N):
        x,y = self.Pi_coords[N][0],  self.Pi_coords[N][1]
       return x,y

    def run(self):
      while True:
        if(self.t == 0):
            self.t=1
            continue
        time.sleep(0.1)

        h = getmtime("Server_dump.txt")
        if self.s != h:
            self.s = h
             with open('Server_dump.txt') as f:
                 m = next(f)
                 y,x = self.Pi_to_chart(int(m))
                 self.taps[x][y] += 1 
                 # but update the document from callback 
                doc.add_next_tick_callback(partial(update, x=x, y=y, taps=self.taps[x][y]))


cla = generator()
cla.chart_dict_gen(15,15)
cla.Pi_dict_gen(15, 15)

x = cla.chart_coords['x']
y = cla.chart_coords['y']
taps = cla.chart_coords['taps']

@gen.coroutine
def update(x, y, taps):
    taps += taps
    print(x,y,taps)
    source.stream(dict(x=[x], y=[y], taps=[taps]))

colors = ["#CCEBFF","#B2E0FF","#99D6FF","#80CCFF","#66c2FF","#4DB8FF","#33ADFF","#19A3FF", "#0099FF", "#008AE6", "#007ACC","#006BB2", "#005C99", "#004C80", "#003D66", "#002E4C", "#001F33", "#000F1A", "#000000"]
mapper = LinearColorMapper(palette=colors, low= 0, high= 15) #low = min(cla.chart_coords['taps']) high = max(cla.chart_coords['taps'])

TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"


p = figure(title="Tou",
           x_range=list(map(str,x)),
           y_range=list(map(str,reversed(y))),
           x_axis_location="above",
           plot_width=900, plot_height=400,
           tools=TOOLS, toolbar_location='below',
           tooltips=[('coords', '@y @x'), ('taps', '@taps%')])

p.grid.grid_line_color = "#ffffff"
p.axis.axis_line_color = "#ef4723"
p.axis.major_tick_line_color = "#af0a36"
p.axis.major_label_text_font_size = "7pt"
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None

p.rect(x="x", y="y",
       width=0.9, height=0.9,
       source=source,
       fill_color={'field': 'taps', 'transform': mapper},
       line_color = "#ffffff",
)

color_bar = ColorBar(color_mapper=mapper,
                     major_label_text_font_size="7pt",
                     ticker=BasicTicker(desired_num_ticks=len(colors)),
                     formatter=PrintfTickFormatter(format="%d%%"),
                     label_standoff=6, border_line_color=None, location=(0, 0))

curdoc().theme = 'dark_minimal'

def ck(attr, old, new):
    print('here') #doesn't even print hi in the terminal if i click anywhere 

source.selected.on_change('indices', ck)


p.add_layout(color_bar, 'right')

doc.add_root(p)

thread = cla
thread.start()

我什至想在终端机上打印一个 hi 但什么都没有

您实际上根本没有在绘图中添加任何选择工具,因此从未进行过任何选择。您已指定:

TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom"

这些是将要添加的唯一工具,其中 none 进行选择,没有任何东西会导致 source.selection.indices 永远更新。如果您正在寻找基于点击的选择,则必须添加 TapTool,例如与

TOOLS = "hover,save,pan,box_zoom,reset,wheel_zoom,tap"

注意多次点击同一个矩形不会重复回调。回调仅在选择 更改 并且连续两次单击相同字形导致相同选择时触发。