Python Bokeh CustomJS: отладка обратного вызова JavaScript для Taping-Tool - PullRequest
0 голосов
/ 19 февраля 2019

Я работаю с Python 3.6.2 и Bokeh 1.0.4 для создания пользовательского обратного вызова JavaScript на моем графике.

Нажав на одну из точек на графике, я бы хотел, чтобы все точки разделяли одно и то жеатрибут в столбце id, который нужно выделить.

Выполнение итерации по всем точкам данных с помощью JavaScript и манипулирование соответствующим атрибутом selected в объекте ColumnDataSource должно помочь.К сожалению, я не могу понять, как исправить этот код.

# Import packages
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS, HoverTool, TapTool


# Create the data for the points
x = [0, 1, 2, 3]
y = [0, 1, 0, 1]
ids = ['A','B','A','B']

data = {'x':x, 'y':y, 'id':ids}
source = ColumnDataSource(data)


# Add tools to the plot
tap = TapTool()
hover = HoverTool(tooltips=[("X", "@x"),
                            ("Y", "@y"),
                            ("ID", "@id")])


# Create a plotting figure
p = figure(plot_width=400, plot_height=400, tools=[tap,hover])


# Code for the callback
code = """
// Set column name to select similar glyphs
var column = 'id';

// Get data from ColumnDataSource
var data = source.data;

// Get indices array of all selected items
var selected = source.selected.indices;

// Array to store glyph-indices to highlight
var select_inds = [];


// Check if only a single glyph is selected
if(selected.length==1){

    // Get the value of the column to find similar attributes/glyphs
    attribute_value = data[column][selected[0]];

    // Iterate over all entries in the ColumnDataSource
    for (var i=0; i<data[column].length; ++i){

        // Check if items have the same attribute
        if(data[column][i]==attribute_value){

            // Add index to selected list
            select_inds.push(i);
            }
        }
    }

// Set selected glyphs in ColumnDataSource
source.selected.indices = select_inds;

// Save changes to ColumnDataSource
source.change.emit();
"""


# Create a CustomJS callback with the code and the data
callback = CustomJS(args={'source':source}, code=code)

# Add the callback to the ColumnDataSource
source.callback=callback


# Plots circles
p.circle('x', 'y', source=source, size=25, color='blue', alpha=1, hover_color='black', hover_alpha=1)

# Show plot
show(p)

более старая версия этой проблемы с Bokeh 0.13.0 не смогла решить мою проблему.

1 Ответ

0 голосов
/ 20 февраля 2019

Вы были почти там!Обратный вызов должен быть добавлен к TapTool вместо ColumnDataSource.

# Import packages
from bokeh.plotting import figure, show
from bokeh.models import ColumnDataSource, CustomJS, HoverTool, TapTool


# Create the data for the points
x = [0, 1, 2, 3]
y = [0, 1, 0, 1]
ids = ['A','B','A','B']

data = {'x':x, 'y':y, 'id':ids}
source = ColumnDataSource(data)


# Add tools to the plot
tap = TapTool()
hover = HoverTool(tooltips=[("X", "@x"),
                            ("Y", "@y"),
                            ("ID", "@id")])


# Create a plotting figure
p = figure(plot_width=400, plot_height=400, tools=[tap,hover])


# Code for the callback
code = """
// Set column name to select similar glyphs
var column = 'id';

// Get data from ColumnDataSource
var data = source.data;

// Get indices array of all selected items
var selected = source.selected.indices;

// Array to store glyph-indices to highlight
var select_inds = [];

// Check if only a single glyph is selected
if(selected.length==1){

    // Get the value of the column to find similar attributes/glyphs
    attribute_value = data[column][selected[0]];

    // Iterate over all entries in the ColumnDataSource
    for (var i=0; i<data[column].length; ++i){

        // Check if items have the same attribute
        if(data[column][i]==attribute_value){

            // Add index to selected list
            select_inds.push(i);
            }
        }
    }

// Set selected glyphs in ColumnDataSource
source.selected.indices = select_inds;

// Save changes to ColumnDataSource
source.change.emit();
"""


# Create a CustomJS callback with the code and the data
callback = CustomJS(args={'source':source}, code=code)

# Add the callback to the taptool
tap.callback=callback


# Plots circles
p.circle('x', 'y', source=source, size=25, color='blue', alpha=1, hover_color='black', hover_alpha=1)

# Show plot
show(p)
...