Python Plotly Chart to Dash

Viewed 287

I have a plot that I've created with plotly that's interactive with clicks and widgets within Jupyter. I'm happy with how my plot works and I want to export it to use outside of Jupyter using dash. When I take my figure and try to output it with dash all the interactive functions I've created through plotly in Jupyter don't work. When I run the code the figure and layout are present, but the interactive part is gone. If I comment out running this on the app.run_server everything works great. All my functions in plotly use @out.capture() then xx.on_click(function) and I use widgets.Button or widgets.FloatText. Are there changes that I need to make to my capture functions to work in dash? Any suggestions are appreciated!

import pandas as pd
import numpy as np
import io
import os
import plotly.graph_objects as go
import json
import ipywidgets as widgets
from dash import Dash, dcc, html

app=Dash(__name__)

x=np.random.uniform(-10,10,size=50)
y=np.sin(x)

# Initialize the figure using plotly
fig=go.FigureWidget([go.Scatter(x=x,
                                y=y,
                                mode='markers',
                                opacity=1,
                                marker=dict(
                                    color=['#a3a7e4']*100,
                                    size=[10]*100)
                               ),
                     go.Scatter(x=[],
                                y=[],
                                mode='lines',
                                marker=dict(
                                    color='DarkSlateGrey')
                               )])

fig.update_layout(
    template='simple_white',
    showlegend=False,
    title='Title',
    xaxis=dict(title="X Axis",
               mirror=True,
              ),
    yaxis=dict(title='Y Axis',
               mirror=True,
              )
)

scatter=fig.data[0]
line = fig.data[1]

# Create the box on the bottom to append the data in the output
out = widgets.Output(layout={'border': '1px solid black'})
out.append_stdout('\n')

reset = widgets.Button(description="Reset")
export = widgets.Button(description="Export")
enter_text=widgets.FloatText(description='Text:')

# Create our callback function
@out.capture()
def update_point(trace, points, selector):
    x = list(line.x) + points.xs
    y = list(line.y) + points.ys
    line.update(x=x, y=y)
    
    c = list(scatter.marker.color)
    s = list(scatter.marker.size)
    for i in points.point_inds:
        c[i] = '#bae2be'
        s[i] = 20
        with fig.batch_update():
            scatter.marker.color = c
            scatter.marker.size = s
    
# Function to clear the output when 'Reset' button is clicked
@out.capture()
def on_reset_clicked(b):
    line.update(x=[], y=[])
    scatter.marker.color=['#a3a7e4']*100
    scatter.marker.size=[10]*100
    out.clear_output()

# Function for exporting the points clicked
@out.capture()
def on_export_clicked(b):
        line.update(x=[],y=[])
        scatter.marker.color=['#a3a7e4']*100
        scatter.marker.size=[10]*100        
        out.clear_output

reset.on_click(on_reset_clicked)
export.on_click(on_export_clicked)
scatter.on_click(update_point)

widgets.VBox([widgets.HBox([reset, export,enter_text]), widgets.VBox([fig, out])])

app.layout=html.Div([
    dcc.Graph(
        id='Title',
        figure=fig
    )
])

if __name__=='__main__':
    app.run_server(debug=False)
0 Answers
Related