Рисунок не сохраняется в графике вне функции. Как это исправить?

У меня есть функция, которая берет график matplotlib и превращает его в график, используя tls.matplotlib_to_pyplot. В конце концов я назвал его plotly_fig. Теперь я пытаюсь добавить ползунки в веб-приложение тире. Но когда я его компилирую, я получаю сообщение об ошибке, говорящее, что plotly_fig не определен. Ниже приведен пример кода, который воссоздает ошибку.

import dash
import dash_core_components as dcc
import dash_html_components as html
import numpy as np
from numpy.linalg import matrix_power
import matplotlib.pyplot as plt
import plotly.tools as tls
from mpl_toolkits.mplot3d import Axes3D
from dash.dependencies import Input, Output
app = dash.Dash()
#begin with the knobs
app.layout = html.Div([
   dcc.Graph(
       id = 'graph',
       figure = plotly_fig),

   html.Label('Config L'), ## this is the knob for the length
   dcc.Slider(
       id = 'l',
       min = 5,
       max = 10,
       marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(5,10)},
       value = L,
   ),

   html.Label('Config n'), ##knob for the n-gon
   dcc.Slider(
       id = 'n',
       min = 0,
       max = 10,
       marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(1,10)},
       value = n,
   ),

   html.Label('Config N'),  ##knob for the number of n-gons outside initial
   dcc.Slider(
       id = 'N',
       min = 0,
       max = 10,
       marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(1,10)},
       value = N,
   ),

   html.Label('Config r'),  ##knob for r only works on integers for now
   dcc.Slider(
       id = 'r',
       min = 0,
       max = 2,
       marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in    range(1,2)},
       value = r,
   ),

   html.Label('Config d'), ##knoc for the depth of the dip
   dcc.Slider(
       id = 'd',
       min = 0,
       max = 2,
       marks = {i: 'Label ={}'.format(i) if i == 1 else str(i) for i in range(1,2)},
       value = d,
)
],
style = {'columnCount': 1})
@app.callback(
   dash.dependencies.Output('graph', 'figure'),
   [dash.dependencies.Input('l', 'value'),
   dash.dependencies.Input('n', 'value'),
   dash.dependencies.Input('N', 'value'),
   dash.dependencies.Input('r', 'value'),
   dash.dependencies.Input('d', 'value')])

def output(L,n,N,r,d):
    x = np.linspace(np.pi, L*n*N*r*d*np.pi, 1000)
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(x, sinx)
    plotly_fig = tls.mpl_to_plotly(mpl_fig)
    return{plotly_fig}
if __name__=='__main__':
    app.run_server(debug = True)

Что я делаю не так?


person SuperSalami    schedule 01.02.2019    source источник


Ответы (1)


Проблема в том, что переменная plotly_fig даже не объявлена, когда вы пытаетесь использовать ее в поле figure графика. Он просто объявляется локально в обратном вызове.

Не требуется явно устанавливать свойство figure графика, оно будет автоматически сопоставлено во время обратного вызова, поэтому вы можете сделать это напрямую следующим образом:

#your code here

app = dash.Dash()
#begin with the knobs
app.layout = html.Div([
   dcc.Graph(
       id = 'graph'),  # ==> here you can remove the figure as it will be automatically set during the callback.

    #your code here
],

style = {'columnCount': 1})

@app.callback(
   dash.dependencies.Output('graph', 'figure'), #here figure represents the field
   [dash.dependencies.Input('l', 'value'),
   dash.dependencies.Input('n', 'value'),
   dash.dependencies.Input('N', 'value'),
   dash.dependencies.Input('r', 'value'),
   dash.dependencies.Input('d', 'value')])

def output(L,n,N,r,d):
    #your code here
    plotly_fig = tls.mpl_to_plotly(mpl_fig)
    return{plotly_fig}

if __name__=='__main__':
    app.run_server(debug = True)

В приведенном выше фрагменте свойство value ползунка является входом приложения, а выход приложения — свойством figure графика. Всякий раз, когда значение ползунка изменяется, Dash вызывает функцию обратного вызова output с новыми входными значениями. Функция фильтрует фрейм данных с этим новым значением, создает объект фигуры и возвращает его в приложение Dash.

Между тем, если вы хотите, чтобы значение по умолчанию было установлено еще до вызова функции обратного вызова, вы можете объявить plotly_fig как глобальную переменную следующим образом:

#your code here
plotly_fig = None # declare the default figure here

app = dash.Dash()
#begin with the knobs
app.layout = html.Div([
   dcc.Graph(
       id = 'graph', figure = plotly_fig),

    #your code here
],

style = {'columnCount': 1})

@app.callback(
   dash.dependencies.Output('graph', 'figure'),
   [dash.dependencies.Input('l', 'value'),
   dash.dependencies.Input('n', 'value'),
   dash.dependencies.Input('N', 'value'),
   dash.dependencies.Input('r', 'value'),
   dash.dependencies.Input('d', 'value')])

def output(L,n,N,r,d):
    #your code here
    plotly_fig = tls.mpl_to_plotly(mpl_fig)
    return{plotly_fig}

if __name__=='__main__':
    app.run_server(debug = True)

Для получения дополнительной информации обратитесь к официальной странице документации, которая имеет аналогичный пример,

https://dash.plot.ly/getting-started-part-2

person n00b    schedule 01.02.2019