Unable to run dash_interactive_graphviz - python

I created a huge Graphviz Network, which I now want to spice up with some interactivity. For this goal I discovered the package dash_interactive_graphviz. From my understanding I can simple provide my existing graph, but I'm already failing to execute the provided sample (see below):
import dash_interactive_graphviz
dot_source = """
digraph {
node[style="filled"]
a ->b->d
a->c->d
}
"""
dash_interactive_graphviz.DashInteractiveGraphviz(
id="graph",
dot_source=dot_source
)
The package itself and all requirements are fulfilled. I run the sample code from above in Visual Studio Code, but nothing happens (no output, no message, no error).
Anybody who can point me in the right direction? Thanks.

You are in the right direction, just need a few steps. I think you can check out this example here to run your file:
https://github.com/BusinessOptics/dash_interactive_graphviz/blob/master/usage.py
import dash_interactive_graphviz
import dash
from dash.dependencies import Input, Output
import dash_html_components as html
import dash_core_components as dcc
app = dash.Dash(__name__)
initial_dot_source = """
digraph {
node[style="filled"]
a ->b->d
a->c->d
}
"""
app.layout = html.Div(
[
html.Div(
dash_interactive_graphviz.DashInteractiveGraphviz(id="gv"),
style=dict(flexGrow=1, position="relative"),
),
html.Div(
[
html.H3("Selected element"),
html.Div(id="selected"),
html.H3("Dot Source"),
dcc.Textarea(
id="input",
value=initial_dot_source,
style=dict(flexGrow=1, position="relative"),
),
html.H3("Engine"),
dcc.Dropdown(
id="engine",
value="dot",
options=[
dict(label=engine, value=engine)
for engine in [
"dot",
"fdp",
"neato",
"circo",
"osage",
"patchwork",
"twopi",
]
],
),
],
style=dict(display="flex", flexDirection="column"),
),
],
style=dict(position="absolute", height="100%", width="100%", display="flex"),
)
#app.callback(
[Output("gv", "dot_source"), Output("gv", "engine")],
[Input("input", "value"), Input("engine", "value")],
)
def display_output(value, engine):
return value, engine
#app.callback(Output("selected", "children"), [Input("gv", "selected")])
def show_selected(value):
return html.Div(value)
if __name__ == "__main__":
app.run_server(debug=True)

Related

Dash plotly app with Heroku: works well heroku locally but dosent work propely in production

I have a dash plotly python jupyter notebook app (music) that takes 5 rows as a sample from a bigger dataframe using df_sample= df.sample(5). It has a quiz with inputs to compare the response of the users with the df_sample and take points depending on the users response and the df_sample values.
When I test it locally the code works perfectly also when I run it locally through heroku local.
But When I deploy to Heroku in production the code fail because df_sample will takes two differents set of values, when the app is updating during the callbacks and then comparison between the users response and the the df_sample dataframe fails.
example:
df_sample('name')=('c','f', 'g', 'b', 'e')
when i use locally this is constant during the callbacks & every works fine
df_sample('name')=('c','f', 'g', 'b', 'e')
df_sample('name')=('b','i', 'l', 'm', 'o')
when I deploy to heroku df_sample get 2 different set of vales during the callbacks and the app fails
here an extract of the code:
Import requests
Import pandas as pd
Import dash
from dash.dependencies import Input, Output
Import dash_html_components as html
Import dash_core_components as dcc
from dash import Dash
from dash import dcc
from dash import html
url1='url'
download = github_session.get(url1).content
df_link = pd.read_csv(io.StringIO(download.decode('latin-1')), sep=";",
error_bad_lines=False, warn_bad_lines=False, encoding='latin-1')
server = app.server
df_sample=df_link.sample(5)
df_sample.reset_index(inplace=True)
compositors= dbc.Col(
dcc.Dropdown(
id="compositor",
options=[
{"label": str(i), "value": i} for i in autors
],
value="",
clearable=False,
)
dbc.Row(
[
dbc.Label("5-look The correct answer is:",
width="auto"),
dbc.Col(
dbc.Input(id="name", value=compositor_result, type="text",size="lg")
)
]
)
dbc.Col(dbc.Button("4-Submmit & play next record", color="danger",
id="example-button",
n_clicks=0)
),
dbc.Col(
dbc.Input(id="result", value=result, type="text",size="lg")
)
app.layout = ....
#app.callback(
Output("result", "value"),
Output("compositor_result", "value"),
Input('example-button', 'n_clicks'),
State("compositor", "value"),
def update_line_chart(n_clicks, compositor):
global value1
global df_sample
if (n_clicks==None):
raise prevent_update
if df:_sample[n_clicks-1]==compositor:
result=value1+15
else: value1=value1
compositor_result=df_sample.name[n_click-1]
return result, compositor_result
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
Thanks

Faster serializations (pickle, parquet, feather, ...) than json in plotly dash Store?

Context
In a dashboard using plotly Dash I need to perform an expensive download from DB only when a component (DataPicker with the period to consider and so to be downloaded from DB) is updated and then use the resulting DataFrame with other components (e.g. Dropdowns filtering the DataFrame) avoiding the expensive download process.
The docs suggests to use dash_core_components.Store as Output of a callback that return the DataFrame serielized in json and than use the Store as Input of other callbacks that needs to deserialize from json to DataFrame.
Serialization from/to JSON is slow, and each time I update a component it takes 30 seconds to update the plot just for that.
I tried to use faster serializations like pickle, parquet and feather but in the deserialization part I get an error stating that the object is empty (when using JSON no such error appear).
Question
Is it possible to perform serializations in Dash Store with faster methods like pickle, feather or parquet (they takes approx half of time for my dataset) than JSON? How?
Code
import io
import traceback
import pandas as pd
from datetime import datetime, date, timedelta
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output
from plotly.subplots import make_subplots
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
today = date.today()
app.layout = html.Div([
dbc.Row(dbc.Col(html.H1('PMC'))),
dbc.Row(dbc.Col(html.H5('analysis'))),
html.Hr(),
html.Br(),
dbc.Container([
dbc.Row([
dbc.Col(
dcc.DatePickerRange(
id='date_ranges',
start_date=today - timedelta(days=20),
end_date=today,
max_date_allowed=today, display_format='MMM Do, YY',
),
width=4
),
]),
dbc.Row(
dbc.Col(
dcc.Dropdown(
id='dd_ycolnames',
options=options,
value=default_options,
multi=True,
),
),
),
]),
dbc.Row([
dbc.Col(
dcc.Graph(
id='graph_subplots',
figure={},
),
width=12
),
]),
dcc.Store(id='store')
])
#app.callback(
Output('store', 'data'),
[
Input(component_id='date_ranges', component_property='start_date'),
Input(component_id='date_ranges', component_property='end_date')
]
)
def load_dataset(date_ranges_start, date_ranges_end):
# some expensive clean data step
logger.info('loading dataset...')
date_ranges1_start = datetime.strptime(date_ranges_start, '%Y-%m-%d')
date_ranges1_end = datetime.strptime(date_ranges_end, '%Y-%m-%d')
df = expensive_load_from_db(date_ranges1_start, date_ranges1_end)
logger.info('dataset to json...')
#return df.to_json(date_format='iso', orient='split')
return df.to_parquet() # <----------------------
#app.callback(
Output(component_id='graph_subplots', component_property='figure'),
[
Input(component_id='store', component_property='data'),
Input(component_id='dd_ycolnames', component_property='value'),
],
)
def update_plot(df_bin, y_colnames):
logger.info('dataset from json')
#df = pd.read_json(df_bin, orient='split')
df = pd.read_parquet(io.BytesIO(df_bin)) # <----------------------
logger.info('building plot...')
traces = []
for y_colname in y_colnames:
if df[y_colname].dtype == 'bool':
df[y_colname] = df[y_colname].astype('int')
traces.append(
{'x': df['date'], 'y': df[y_colname].values, 'name': y_colname},
)
fig = make_subplots(
rows=len(y_colnames), cols=1, shared_xaxes=True, vertical_spacing=0.1
)
fig.layout.height = 1000
for i, trace in enumerate(traces):
fig.append_trace(trace, i+1, 1)
logger.info('plotted')
return fig
if __name__ == '__main__':
app.run_server(host='localhost', debug=True)
Error text
OSError: Could not open parquet input source '<Buffer>': Invalid: Parquet file size is 0 bytes
Due to the exchange of data between client and server, you are currently limited to JSON serialization. One way to circumvent this limitation is via the ServersideOutput component from dash-extensions, which stores the data on the server. It uses file storage and pickle serialization by default, but you can use other storage (e.g. Redis) and/or serialization protocols (e.g. arrow) as well. Here is a small example,
import time
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from dash_extensions.enrich import Dash, Output, Input, State, ServersideOutput
app = Dash(prevent_initial_callbacks=True)
app.layout = html.Div([
html.Button("Query data", id="btn"), dcc.Dropdown(id="dd"), dcc.Graph(id="graph"),
dcc.Loading(dcc.Store(id='store'), fullscreen=True, type="dot")
])
#app.callback(ServersideOutput("store", "data"), Input("btn", "n_clicks"))
def query_data(n_clicks):
time.sleep(1)
return px.data.gapminder() # no JSON serialization here
#app.callback(Input("store", "data"), Output("dd", "options"))
def update_dd(df):
return [{"label": column, "value": column} for column in df["year"]] # no JSON de-serialization here
#app.callback(Output("graph", "figure"), [Input("dd", "value"), State("store", "data")])
def update_graph(value, df):
df = df.query("year == {}".format(value)) # no JSON de-serialization here
return px.sunburst(df, path=['continent', 'country'], values='pop', color='lifeExp', hover_data=['iso_alpha'])
if __name__ == '__main__':
app.run_server()

Change the language in dash/plotly

I want to change the language of dash's core components and the toolbar in plots (to german). I thought that defining external_scripts would be sufficient, but its still showing everything in english. Here is a minimal example of my code:
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
from datetime import datetime as dt
external_scripts = ["https://cdn.plot.ly/plotly-locale-de-latest.js"]
app = dash.Dash(__name__, external_scripts=external_scripts)
data_canada = px.data.gapminder().query("country == 'Canada'")
fig = px.bar(data_canada, x='year', y='pop')
app.layout = html.Div(children=[
html.H1(children='Dashboard'),
dcc.DatePickerRange(
id="date_range_picker",
min_date_allowed=dt(2018,1,1),
max_date_allowed=dt(2020,12,31),
display_format="MMM, YYYY"
),
dcc.Graph(
id='example-graph',
figure=fig
)
])
if __name__ == '__main__':
app.run_server(debug=True)
What else do I have to do to change the language?
You must add:
config_plots = dict(locale='de')
to:
dcc.Graph(
id='example-graph',
figure=fig,
config=config_plots
)

Dash(Python) - thicker ring in gauge meter of dash-daq

The ring that dash_daq.Gauge outputs is too thin, as you can see from the picture below.
I would like to have thicker ring. I couldn’t find css element under ‘inspect element’ to increase the thickness of ring. How do i go about doing this?
Just create an assets folder and place there your css file e.g. "styles.css" and it works fine (Dash v1.6.0)
styles.css:
circle {
stroke-width: 20px;
}
app.py:
import dash
import dash_daq as daq
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__, assets_folder = 'assets', include_assets_files = True)
app.layout = html.Div([
daq.Gauge(
id='my-gauge',
label="Default",
value=6,
style={'display': 'block' }
),
dcc.Slider(
id='my-gauge-slider',
min=0,
max=10,
step=1,
value=5
),
])
#app.callback(
dash.dependencies.Output('my-gauge', 'value'),
[dash.dependencies.Input('my-gauge-slider', 'value')]
)
def update_output(value):
return value
if __name__ == '__main__':
app.run_server(debug=True)
gauge meter is made up of svg tag. To get an idea i will show the screen shot
Try changing the stroke-width attr value to change the thinkness. i hope this will help you to get inital idea.

Running multi-paged Plotly-Dash app with callbacks and graphs within Flask

Intro:
I already have a multi-page Dash app running with each page into a separate layout file and is callable from main index page.
What works well?
Running a standalone Dash app, ($python index.py), index page is shown with other entries and each link works well, with their graphs and callbacks.
'''
index.py : relevant sections
'''
from appc import app, server
import page1c, page2c, page3c
app.layout = html.Div([
dcc.Location(id='url', refresh=False),
html.Div(id='page-content')
])
...
...
..
index_page = html.Div([ ....
# Similar to calling in flask_app.py
------------------------------------------------------------
'''
appc.py : relevant sections
'''
app = dash.Dash('auth')
auth = dash_auth.BasicAuth(
app,
VALID_USERNAME_PASSWORD_PAIRS
)
server = app.server
app.config.suppress_callback_exceptions = True
...
..
'''
What doesn't work well?
A: Trying to use existing Dash App within a Flask app ($python flask_app.py) but having issue where only HTML content (from layout is shown) but callbacks aren't triggering if Dash layouts are defined in separate files.
Why?
A: Planning to use Flask for main web site and features and Dash for interactive graphs and HTML layout.
Attempted solution:
Below is the code from flask_app.py and i've commented to my best ability.
'''
flask_app.py : Attempt to run dash and flask based routes in one instance.
'''
from flask import Flask, render_template
from dash import Dash
from dash.dependencies import Input, State, Output
import dash_core_components as dcc
import dash_html_components as html
import json
import plotly
import pandas as pd
import numpy as np
server = Flask(__name__)
########################################################################
#server.route('/graph') # Interactive Dash Graph in predefined HTML
def index():
rng = pd.date_range('1/1/2011', periods=7500, freq='H')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
graphs = [
dict(
data=[
dict(
x=[1, 2, 3],
y=[10, 20, 30],
type='scatter'
),
],
layout=dict(
title='first graph'
)
),
dict(
data=[
dict(
x=[1, 3, 5],
y=[10, 50, 30],
type='bar'
),
],
layout=dict(
title='second graph'
)
),
dict(
data=[
dict(
x=ts.index, # Can use the pandas data structures directly
y=ts
)
]
)
]
# Add "ids" to each of the graphs to pass up to the client
# for templating
ids = ['Graph-{}'.format(i) for i, _ in enumerate(graphs)]
# Convert the figures to JSON
# PlotlyJSONEncoder appropriately converts pandas, datetime, etc
# objects to their JSON equivalents
graphJSON = json.dumps(graphs, cls=plotly.utils.PlotlyJSONEncoder)
return render_template('layouts/graph.html',
ids=ids,
graphJSON=graphJSON)
########################################################################
#server.route('/hello') # Static predefined HTML
def hello_index():
return render_template('hello.html',)
########################################################################
app = Dash(server=server, url_base_pathname='/dash') # Interactive Dash input box with callback.
app.layout = html.Div([
html.Div(id='target'),
dcc.Input(id='input', type='text', value=''),
html.Button(id='submit', n_clicks=0, children='Save')
])
#app.callback(Output('target', 'children'), [Input('submit', 'n_clicks')],
[State('input', 'value')])
def callback(n_clicks, state):
return "callback received value: {}".format(state)
######################################################################
app = Dash(__name__, server=server, url_base_pathname='/dashed') #Another Bash Graph inline, no callbacks.
app.layout = html.Div(children=[
html.Div(children='''
Dash: A web application framework for Python
'''),
dcc.Graph(
id='example-graph',
figure={
'data': [
{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
{'x': [1, 2, 3], 'y': [2, 4, 6], 'type': 'bar', 'name': 'Montreal'},
],
'layout': {
'title': 'Dash Data Visualization'
}
}
)
])
########################################################################
'''
Content from 'index.py' : Check above.
page1c, page2c, page3c are dash separate layout files for a multipage website with dash, which is working perfect.
These are called in 'index.py' (main page) respectively as below.
Running 'python index.py' (standalone dash instance), all the interactive pages are responsive and plot the data (with callbacks) they're intended to.
But running with flask, pages only show HTML content, sliders and dropdown boxes, but the backend processes aren't triggering so no graphs are generated.
'''
# Note: 'index_page' is the layout with 3 links to above items.
# All 3 files have multiple layout (with graphs and callbacks), different files for everyone to keep it simple and less cluttered.
import page1c, page2c, page3c
from index import index_page
d_app = Dash(server=server, url_base_pathname='/', )
d_app.layout = html.Div([
html.Div(id='page-content'),
dcc.Location(id='url', refresh=True),
])
#d_app.callback(Output('page-content', 'children'),
[Input('url', 'pathname')])
def display_page(pathname):
if pathname == '/page1':
return page1c.layout
elif pathname == '/page2':
return page2c.layout
elif pathname == '/page3':
return page3c.layout
else:
return index_page
######################################################################
if __name__ == '__main__':
app.run_server(port=9999, debug=True)

Categories