Я реализую ScatterPlot для больших данных, используя Bokeh, DataShader и HoloViews. Сама часть ScatterPlot в значительной степени готова, но есть одно требование, с которым у меня возникли проблемы: мне нужно иметь возможность захватывать координаты данных, когда пользователь делает двойной щелчок.
Я нашел некоторый код, который у меня работает в блокноте Jupyter, но по какой-то причине при переходе на Python и Bokeh Server он не работает.
Вот код:
from os.path import dirname, join
import csv
import holoviews as hv
import datashader as ds
import pandas as pd
#import parambokeh
from holoviews.operation.datashader import aggregate, shade, datashade, dynspread
from holoviews.operation import decimate
from holoviews.streams import RangeXY
from holoviews import streams
from bokeh.plotting import curdoc
hv.extension('bokeh')
class MyScatterPlotBokeh:
#
# PARAMETERS:
# - keyFieldName : Field that uniquely identify a row
# - xFieldName : Field Name used for x-Axis
# - yFieldName : Field Name used for y-Axis
# - colorFieldName : Field Name used to select circle colors
# - otherFieldNames : Comma separated value variable with the name of all fields we want to show data
#
def __init__(self, filePath, title, screenWidth, screenHeight, keyFieldName, xFieldName, yFieldName, colorFieldName, otherFieldNames):
self._screenHeight = screenHeight
self._screenWidth = screenWidth
# Read data from file
df = pd.read_csv(filePath)
df[colorFieldName]=df[colorFieldName].astype("category")
# Creating graphic
hover_opts = hv.opts("QuadMesh [tools=['hover']] (alpha=0 hover_alpha=0.2)")
self._points = hv.Points(df,kdims=[xFieldName,yFieldName])
self._dynamic_hover = datashade(self._points) * dynspread(datashade(self._points, aggregator=ds.count_cat(colorFieldName))) * \
hv.util.Dynamic(aggregate(self._points, width=50, height=50, streams=[RangeXY]),operation=hv.QuadMesh)
# Interaction - Point selection
double_tap = streams.DoubleTap(transient=True, source=self._points)
self._countTap = 0
self._taps = []
def record_taps(x,y):
print "clicked"
self._countTap += 1
if self._countTap>2:
self._countTap = 0
if None not in [x,y]:
if self._countTap == 1:
self._taps.insert(0,(x, y))
else:
self._taps.append((x, y))
print "TAPS LOOK LIKE " + str(self._taps)
return hv.Points(self._taps, vdims='Taps')
self._finalPlot = self._dynamic_hover + hv.DynamicMap(record_taps, streams=[double_tap])
def draw(self):
hv.renderer('bokeh').server_doc(self._finalPlot)
Как только сервер запускается, я вижу сообщение "нажато", но никогда после двойного щелчка в браузере. Похоже на то, что событие двойной щелчок не отвечает. В конце концов мне нужно отправить щелкнутые координаты X и Y в браузер, что, я думаю, я могу сделать, создав поле ввода из кода Python, но я еще не там.
Любая помощь будет оценена.