#python #django #bokeh
#питон #джанго #боке
Вопрос:
я пытаюсь разработать веб-приложение для своей магистерской диссертации. Я использовал Боке для создания интерактивного сюжета и встроил его в приложение django. Проблема в том, что мне не удается что-то сделать с js_on_change или js_on_click группы radiobuttongroup.
Таково мое мнение:
def DTA_webAPP(request): context={} result = None imps = pd.DataFrame(columns=["1","2","3","4","5"]) # i need this to avoid problem in create_grid in plotting.py dta = pd.DataFrame(columns = ["3","4"]) fig = myfig(imps,dta) script,div = components(fig.layout) form = DTAselection(request.POST,request.FILES) if request.method == 'POST' and "Compute" in request.POST: if form.is_valid(): data = pd.read_csv(request.FILES["ImportData"],sep = "t", skiprows = [1,2]) imps, dta = main(data, form['method_of_discretization'].value(),float(form['regularization_parameter'].value()), int(form['regularization_order'].value()), int(form['number_of_point'].value()), form['col_selection'].value()) fig = myfig(imps, dta) script, div = components(fig.layout) imps.to_csv("result_imps.csv", index = False) dta.to_csv("result_dta.csv", index = False) result = "Ok, boy" context = {'form': form, 'script':script, 'div':div, "result":result} return HttpResponse(render(request, "dta_webapp.html", context))
рисунок создан в классе myfig.
Это мой класс myfig:
LABELS = ["IMPS","REAL RESIDUALS", "IMAG RESIDUALS"] class myfig(object): def __init__(self, df_data, df_dta): self.df_data = df_data self.df_dta = df_dta self.radio_button_group = RadioButtonGroup(labels=LABELS, active=0) self.source = None self.plot = self.create_grid() self.radio_button_group.js_on_change('active', CustomJS(args= dict(s=self.source, p = self.plot.children[0], x = self.df_data.columns[1], y = self.df_data.columns[2], ), code=""" console.log('radio_button_group: active=' this.active, this.toString()); const s1 = new Bokeh.ColumnDataSource({data : {x: [3,4,5,6,6] , y:[3,4,5,6,4] } }) ; s = s1; s.change.emit(); """)) self.layout = layout([ [self.radio_button_group], [self.plot], ]) def create_grid(self): plot_data=figure(title= "IMPS", x_axis_label="Y'", y_axis_label="Y''") source_data = ColumnDataSource(data = self.df_data) vec_size = np.arange(0,len(self.df_data.columns), 1,dtype=int) #columns = int(len(self.df_data.columns)/(len(self.df_data.columns)/5))) data_to_plot = vec_size.reshape(int(len(self.df_data.columns)/5),5) palettes_ = RdYlGn[vec_size.size] self.source = source_data for number, fix_voltage in enumerate(data_to_plot): plot_data.circle(x = self.df_data.columns[fix_voltage[1]], y = self.df_data.columns[fix_voltage[2]], source = self.source,color=palettes_[number]) plot_data.line(x = self.df_data.columns[fix_voltage[3]], y = self.df_data.columns[fix_voltage[4]], source = self.source, color = palettes_[number], line_dash = "dashed") #plot_data.add_layout(LinearAxis(y_range_name="Y''"), 'left') #plot_data.add_layout(LinearAxis(x_range_name="Y'"), 'below') freq = "@" self.df_data.columns[0] TOOLTIPS=[ ("freq" ,freq), ("x", "$x"), ("y", "$y"),] plot_data.add_tools(HoverTool(tooltips=TOOLTIPS)) plot_dta = figure(title="DTA result", x_axis_type="log",x_axis_label="Time (s)", y_axis_label="DTA (V^-1)") source_dta = ColumnDataSource(data = self.df_dta) vec_size = np.arange(0,len(self.df_dta.columns), 1,dtype=int) data_to_plot = vec_size.reshape(int(len(self.df_dta.columns)/2),2) for number, fix_voltage in enumerate(data_to_plot): plot_dta.line(x = self.df_dta.columns[fix_voltage[0]], y = self.df_dta.columns[fix_voltage[1]], source = source_dta,color = palettes_[number],) freq ="@" self.df_data.columns[0] TOOLTIPS=[ ("tau", "$x"), ("DTA", "$y"),] plot_dta.add_tools(HoverTool(tooltips=TOOLTIPS)) grid = row(plot_data, plot_dta) return grid
Я поместил это в свою html-голову:
lt;!-- BOKEH DEPENDENCIES --gt; lt;link href="http://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.css" rel="stylesheet" type="text/css"gt; lt;link href="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.4.0.min.css" rel=”stylesheet” type=”text/css”gt;
и это в самом конце моего html:
lt;/bodygt; lt;script src="https://cdn.bokeh.org/bokeh/release/bokeh-2.4.2.min.js"gt;lt;/scriptgt; lt;script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.4.2.min.js"gt;lt;/scriptgt; lt;script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.4.2.min.js"gt;lt;/scriptgt; lt;script src="https://cdn.bokeh.org/bokeh/release/bokeh-api-2.4.2.min.js"gt;lt;/scriptgt; {{ script |safe}} lt;/htmlgt;
Я использую Боке==2.4.2. В исходниках css я поставил версию 1.4.0, так как с 2.4.2 в качестве версии возникла ошибка. GET https://cdn.pydata.org/bokeh/release/bokeh-2.4.2.min.css net::ERR_ABORTED 403
, но я думаю, что написание предыдущей версии css не является проблемой в вопросе, который я задал.
Предупреждение, которое я получил в компиляторе, заключается в следующем: я много чего перепробовал, но моя фигура никогда не обновляется, если я меняю радиоактивную кнопку. Единственное, что мне удалось получить, — это создание новой фигуры с Боке.Построение графика.показать(построить) в обратном вызове js, но это не то, что я хочу. Я хочу радикально изменить в xaxis и yaxis имя, заголовок и данные двух фигур в self.plot, созданных методом create_grid(). Этот метод возвращает строку(рис. 1, рис. 2), которая хранится в self.plot. Я хочу взять под контроль фигуру 1, фигуру 2 с помощью обратного вызова . Я попытался обновить ColumnDataSource, но ничего, я попытался изменить весь сюжет и сделать plot.change.emit (), но ничего. Что не так в моем подходе?
Комментарии:
1. как вы его внедряете ? Где ваш HTML-код? Возможно, потребуется загрузить код JavaScript для связи между браузером и сервером. Вы также можете проверить DevTools, если нет сообщений об ошибках. Возможно, также потребуется проверить вкладку Сеть в DevTools, чтобы проверить, нет ли проблем с загрузкой некоторых элементов — кода JavaScript.
2. я отредактировал свой вопрос, добавив html и предупреждающее сообщение в DevTools.