2017-01-30 5 views
0

Я пытаюсь построить несколько строк в графике на основе пользовательских параметров «MultiSelect». Я читаю в двух отдельных файлах excel данных и строю их ось по запросу пользователя. Я использую Python 3.5 и работаю на MAC.Bokeh MultiSelect прорисовка в бесконечном цикле, искажающий график

1). Как только я делаю мультиселекцию, цифра искажается

2). Кажется, что график работает в бесконечном цикле.

3). Дозировки участка не обновляются должным образом, когда пользователь меняет выбор. Он просто добавляет больше сюжетов, не удаляя предыдущий сюжет.

from os.path import dirname, join 
from pandas import * 

import numpy as np 
import pandas.io.sql as psql 
import sqlite3 as sql 
import sys, os 

from bokeh.plotting import figure 
from bokeh.layouts import layout, widgetbox 
from bokeh.models import ColumnDataSource, HoverTool, Div 
from bokeh.models.widgets import Slider, Select, TextInput, MultiSelect 
from bokeh.io import curdoc 
import matplotlib.pyplot as plt 

files = list() 
path = os.getcwd() 
for x in os.listdir(path): 
    if x.endswith(".xlsx"): 
    if x != 'template.xlsx' : 
    files.append(x) 

axis_map = { 
    "0% void": "0% void", 
    "40% void": "40% void", 
    "70% void": "70% void", 
} 


files_list = MultiSelect(title="Files", value=["dummy2.xlsx"],  
options=open(join(dirname(__file__), 'files.txt')).read().split()) 
voids = MultiSelect(title="At what void[s]", value=["0% void"], options=sorted(axis_map.keys())) 

p = figure(plot_height=600, plot_width=700, title="", toolbar_location=None) 
pline = figure(plot_height=600, plot_width=700, title="") 

path = os.getcwd() 
data_dict = {} 
for file in os.listdir(path): 
if file.endswith(".xlsx"): 
    xls = ExcelFile(file) 
    df = xls.parse(xls.sheet_names[0]) 
    data = df.to_dict() 
    data_dict[file] = data 


# converting dictionary to dataframe 
newdict = {(k1, k2):v2 for k1,v1 in data_dict.items() \ 
         for k2,v2 in data_dict[k1].items()} 
xxs = DataFrame([newdict[i] for i in sorted(newdict)], 
        index=MultiIndex.from_tuples([i for i in sorted(newdict.keys())])) 
master_data = xxs.transpose() 

def select_data(): 
    for vals in files_list.value: 
     for vox in voids.value: 
      pline.line(x=master_data[vals]['Burnup'], y= master_data[vals][vox]) 
      pline.circle(x=master_data[vals]['Burnup'], y= master_data[vals][vox]) 
    return 



def update(): 
    select_data() 

controls = [ files_list, voids] 

for control in controls: 
    control.on_change('value', lambda attr, old, new: update()) 

sizing_mode = 'fixed' # 'scale_width' also looks nice with this example 

inputs = widgetbox(*controls, sizing_mode=sizing_mode) 
l = layout([ 
    [inputs, pline], 
], sizing_mode=sizing_mode) 

update() 

curdoc().add_root(l) 
curdoc().title = "Calculations" 

ответ

0

Я не 100% уверен, так как приведенный выше код не является самодостаточным и не может быть запущен и исследован, но есть некоторые вопросы (по Bokeh 0.12.4) с добавлением новых компонентов для документов, являющихся проблематичным в некоторых ситуациях. Эти проблемы высоки в списке приоритетов для следующих двух точечных выпусков.

Являются ли размеры данных разумными, чтобы вы могли создать все комбинации спереди? Если это так, я бы рекомендовал сделать это, а затем, имея значения multi-select, соответствующим образом переключить видимость вкл./Выкл. Например, вот подобный пример с помощью флажка:

import numpy as np 

from bokeh.io import curdoc 
from bokeh.layouts import row 
from bokeh.palettes import Viridis3 
from bokeh.plotting import figure 
from bokeh.models import CheckboxGroup 

p = figure() 
props = dict(line_width=4, line_alpha=0.7) 
x = np.linspace(0, 4 * np.pi, 100) 
l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props) 
l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props) 
l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props) 

checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], active=[0, 1, 2], width=100) 

def update(attr, old, new): 
    l0.visible = 0 in checkbox.active 
    l1.visible = 1 in checkbox.active 
    l2.visible = 2 in checkbox.active 

checkbox.on_change('active', update) 

layout = row(checkbox, p) 
curdoc().add_root(layout) 

Если размеры данных являются не таким образом, что вы можете создать все комбинации фронт, то я бы предложил сделать вопрос о project issue trackerhttps://github.com/bokeh/bokeh/issues), который имеет полный, минимальный, автономный, исполняемый код as-is для воспроизведения проблемы (т. е. генерирует случайные или синтетические данные, но в остальном они идентичны). Это первое, что поможет основным разработчикам решить проблему быстрее.

0

@bigreddot Спасибо за ваш ответ.

Я отредактировал код, чтобы сделать его автономным.

1). График не сбрасывается. Новые выбранные сюжеты по предыдущему сюжету.

2). Когда пользователь делает множественный выбор (Ctrl + Shift) ось участок искажается, и кажется, работает в бесконечном цикле

from pandas import * 
 

 
import numpy as np 
 
import sys, os 
 

 
from bokeh.plotting import figure 
 
from bokeh.layouts import layout, widgetbox 
 
from bokeh.models.widgets import MultiSelect 
 
from bokeh.io import curdoc 
 
from bokeh.plotting import reset_output 
 
import math 
 

 
axis_map = { 
 
    "y1": "y3", 
 
    "y2": "y2", 
 
    "y3": "y1", 
 
} 
 

 
x1 = np.linspace(0,20,62) 
 
y1 = [1.26 * math.cos(x) for x in np.linspace(-1,1,62) ] 
 
y2 = [1.26 * math.cos(x) for x in np.linspace(-0.95,.95,62) ] 
 
y3 = [1.26 * math.cos(x) for x in np.linspace(-.9,.90,62) ] 
 

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

 
vars = MultiSelect(title="At what void[s]", value=["y1"], options=sorted(axis_map.keys())) 
 

 
master_data = { 'rate' : x1, 
 
       'y1' : y1, 
 
       'y2' : y2, 
 
       'y3' : y3    
 
       } 
 
       
 
p = figure(plot_height=600, plot_width=700, title="", toolbar_location=None) 
 
pline = figure(plot_height=600, plot_width=700, title="", tools=TOOLS) 
 

 
def select_data(): 
 
     for vox in vars.value: 
 
      pline.line(x=master_data['rate'], y= master_data[vox], line_width=2) 
 
      pline.circle(x=master_data['rate'], y=master_data[vox], line_width=2) 
 
     return 
 

 
controls = [ vars] 
 

 
for control in controls: 
 
    control.on_change('value', lambda attr, old, new: select_data()) 
 

 

 
sizing_mode = 'fixed' 
 

 
inputs = widgetbox(*controls) 
 
l = layout([ 
 
    [inputs, pline], 
 
]) 
 

 
select_data() 
 

 
curdoc().add_root(l) 
 
curdoc().title = "Plot"

Смежные вопросы