Bokeh 1.0.4 - выбор по нескольким глифам с интерактивной легендой не включает все глифы - PullRequest
0 голосов
/ 04 марта 2019

Я использую интерактивные легенды, как в примере ниже

import pandas as pd

from bokeh.palettes import Spectral4
from bokeh.plotting import figure, output_file, show
from bokeh.sampledata.stocks import AAPL, IBM, MSFT, GOOG

p = figure(plot_width=800, plot_height=250,
           tools=('pan, lasso_select, reset'),
           active_drag='lasso_select',
           x_axis_type="datetime")
p.title.text = 'Click on legend entries to mute the corresponding lines'

for data, name, color in zip([AAPL, IBM, MSFT, GOOG], ["AAPL", "IBM", "MSFT", "GOOG"], Spectral4):
    df = pd.DataFrame(data)
    df['date'] = pd.to_datetime(df['date'])
    p.circle(df['date'], df['close'], line_width=2, color=color, alpha=0.8,
             #selection_color='black',
             nonselection_color='gray',
             muted_color='gray', muted_alpha=0.2, legend=name)

p.legend.location = "top_left"
p.legend.click_policy="mute"

output_file("interactive_legend.html", title="interactive_legend.py example")

show(p)

Если я сделаю выделение с помощью инструмента «Лассо», как это: while selecting with lasso

послеотпуская мышь, я вижу:

after selecting

Обратите внимание, что точки для MSFT и GOOG остаются выделенными, даже если ни одна из них не находилась внутри области выделения.

Я бы хотел, чтобы они стали невыбранными (серыми) в этом случае.

Очевидно, что если ни одна из точек в глифе не находится внутри области выделения, то все точки этого глифа остаются выделенными (т. Е. Инструмент выбора не включает все глифы на рисунке).

Спасибо за помощь!

1 Ответ

0 голосов
/ 29 марта 2019

К сожалению, это поведение по умолчанию LassoSelectTool.Однако я могу предложить вам хороший обходной путь, который скроет глифы, если их точки не выбраны.Затем вы можете использовать ResetTool, чтобы показать их обратно.Я надеюсь, что это сработает для вас.

import pandas as pd
from bokeh.palettes import Spectral4
from bokeh.models import LassoSelectTool, ResetTool, CustomJS, LegendItem, Legend, ColumnDataSource
from bokeh.plotting import figure, output_file, show
from bokeh.sampledata.stocks import AAPL, IBM, MSFT, GOOG

p = figure(plot_width = 800, plot_height = 250,
           tools = ('pan,reset'),
           x_axis_type = "datetime")
p.title.text = 'Click on legend entries to mute the corresponding lines'

sources = []
backup_colors = []
stocks = ["AAPL", "IBM", "MSFT", "GOOG"]
for data, name, color in zip([AAPL, IBM, MSFT, GOOG], stocks, Spectral4):
    df = pd.DataFrame(data)
    df['date'] = pd.to_datetime(df['date'])
    sources.append(ColumnDataSource(dict(x = df['date'], y = df['close'], color = len(df['close'].values) * [color])))
    backup_colors.append(len(df['close'].values) * [color])

renderers = []
for index, name in enumerate(['AAPL', 'IBM', 'MSFT', 'GOOG']):
    source = sources[index]
    renderers.append(p.circle(x = 'x',
                              y = 'y',
                              color = 'color',
                              source = source,
                              line_width = 2,
                              alpha = 0.8,
                              nonselection_color = 'gray',
                              muted_color = 'gray',
                              muted_alpha = 0.2,
                              legend = name))

legend_items = [LegendItem(label = stocks[index], renderers = [renderer], name = stocks[index]) for index, renderer in enumerate(renderers)]
legend = Legend(items = legend_items, name = 'stocks_legend')
p.add_layout(legend)
p.legend.click_policy = 'hide'

greys = len(backup_colors[0]) * ['#888888']
code = '''  selected_line = null;
            for (index in renderers){
                renderer = renderers[index];
                if (renderer.data_source.selected.indices.length > 0)
                {
                    selected_line = renderer.data_source.selected.indices.length
                    break;
                }
            }
            if (selected_line != null){
                for (index in renderers){
                    renderer = renderers[index];
                    if (renderer.data_source.selected.indices.length == 0){     
                        renderer.data_source.data['color'] = greys
                        renderer.data_source.change.emit();
                    }
                }
            }'''
lasso_select_tool = LassoSelectTool(select_every_mousemove = False)
lasso_select_tool.callback = CustomJS(args = dict(renderers = renderers, greys = greys), code = code)
p.add_tools(lasso_select_tool)

p.legend.location = "top_left"
p.legend.click_policy = "mute"

code = '''  for (index in renderers){
                renderer = renderers[index];
                renderer.data_source.data['color'] = colors[index];
                renderer.data_source.change.emit();
            } '''
p.js_on_event('reset', CustomJS(args = dict(renderers = renderers, colors = backup_colors), code = code))

show(p)

Результат:

enter image description here

...