I have this code (from here) and it generates a network as expected:
import dash
import dash_core_components as dcc
from dash import html
import dash_cytoscape as cyto
from dash.dependencies import Input, Output
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
html.P("Dash Cytoscape:"),
cyto.Cytoscape(
id='cytoscape',
elements=[
{'data': {'id': 'ca', 'label': 'Canada'}},
{'data': {'id': 'on', 'label': 'Ontario'}},
{'data': {'id': 'qc', 'label': 'Quebec'}},
{'data': {'source': 'ca', 'target': 'on'}},
{'data': {'source': 'ca', 'target': 'qc'}}
],
layout={'name': 'breadthfirst'},
style={'width': '1000px', 'height': '1000px'}
)
])
if __name__ == '__main__':
app.run_server()
I'm just wondering, would someone know if I'm able to/how to edit this code so that I can click on a node, and it's a hyperlink to a webpage (e.g. in this case could just be the wikipedia page for each node).
You could create a callback which sets the href property of a dcc.Location component based on the clicked node:
app = dash.Dash(__name__)
app.layout = html.Div(
[
dcc.Location(id="location"),
cyto.Cytoscape(
id="cytoscape",
elements=[
{"data": {"id": "ca", "label": "Canada"}},
{"data": {"id": "on", "label": "Ontario"}},
{"data": {"id": "qc", "label": "Quebec"}},
{"data": {"source": "ca", "target": "on"}},
{"data": {"source": "ca", "target": "qc"}},
],
layout={"name": "breadthfirst"},
style={"width": "1000px", "height": "1000px"},
),
]
)
#app.callback(
Output("location", "href"),
Input("cytoscape", "tapNodeData"),
prevent_initial_call=True,
)
def navigate_to_url(node_data):
return f"https://en.wikipedia.org/wiki/{node_data['label']}"
Related
I am trying to create a simple Dash application that includes Dash-Leaflet so that it plots some points as markers. It is apparently working as expected when no styles are applied. But I would like to create a layout with bootstrap with tabs as in this example: https://hellodash.pythonanywhere.com/
When I place the map element within a tab container, it does not render properly. If I move it away it works fine.
This is the code I have so far:
from dash import Dash, dcc, html, dash_table, Input, Output, callback
import plotly.express as px
import dash_bootstrap_components as dbc
import dash_leaflet as dl
import dash_leaflet.express as dlx
from dash_extensions.javascript import assign
import pandas as pd
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
header = html.H4(
"Sample map", className="bg-primary text-white p-2 mb-2 text-center"
)
data = pd.DataFrame([{'name': 'Point 1', 'lat': 39.535, 'lon': 0.0563, 'cluster': 1, 'val_x': 0, 'val_y': 1},
{'name': 'Point 2', 'lat': 40.155, 'lon': -0.0453, 'cluster': 1, 'val_x': 1, 'val_y': 4},
{'name': 'Point 1', 'lat': 38.875, 'lon': 0.0187, 'cluster': 2, 'val_x': 2, 'val_y': 2}])
dropdown = html.Div(
[
dbc.Label("Select Cluster"),
dcc.Dropdown(
data.cluster.unique().tolist(),
id="cluster_selector",
clearable=False,
),
],
className="mb-4",
)
controls = dbc.Card(
[dropdown],
body=True,
)
tab1 = dbc.Tab([dl.Map([dl.TileLayer()], style={'width': '100%',
'height': '50vh',
'margin': "auto",
"display": "block"}, id="map")], label="Map")
tab2 = dbc.Tab([dcc.Graph(id="scatter-chart")], label="Scatter Chart")
tabs = dbc.Card(dbc.Tabs([tab1, tab2]))
app.layout = dbc.Container(
[
header,
dbc.Row(
[
dbc.Col(
[
controls,
],
width=3,
),
dbc.Col([tabs], width=9),
]
),
],
fluid=True,
className="dbc",
)
if __name__ == "__main__":
app.run_server(debug=True, port=8052)
This is what it looks like.
I have tried the proposed solutions on this post but they do not seem to work (or I am applying the wrong)
Do you have any suggestions on where to look for the problem?
Thank you very much.
I am trying to create a simple networkx and dash dashboard with a dropdown to select either successors, predecessors, or connected then when I click on a node it will return that info.
For example, if I select predecessors and then click on Texas, it will provide US, but if I select successors and click on it, it will show Houston.
If I select connected and click on Texas, it will respond with US and Houston.
Would anyone know the correct callback function that I would need to create to accomplish this?
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_cytoscape as cyto
from dash.dependencies import Input, Output
import plotly.express as px
app = dash.Dash(__name__)
app.layout = html.Div([
html.P("Dash Cytoscape:"),
cyto.Cytoscape(
id='cytoscape',
elements=[
{'data': {'id': 'ca', 'label': 'Canada'}},
{'data': {'id': 'on', 'label': 'Ontario'}},
{'data': {'id': 'qc', 'label': 'Quebec'}},
{'data': {'id': 'us', 'label': 'US'}},
{'data': {'id': 'ny', 'label': 'New York'}},
{'data': {'id': 'tx', 'label': 'Texas'}},
{'data': {'id': 'fl', 'label': 'Florida'}},
{'data': {'id': 'mia', 'label': 'Miami'}},
{'data': {'id': 'hou', 'label': 'Houston'}},
{'data': {'source': 'ca', 'target': 'on'}},
{'data': {'source': 'ca', 'target': 'qc'}},
{'data': {'source': 'us', 'target': 'ny'}},
{'data': {'source': 'us', 'target': 'tx'}},
{'data': {'source': 'us', 'target': 'fl'}},
{'data': {'source': 'tx', 'target': 'hou'}},
{'data': {'source': 'fl', 'target': 'mia'}}
],
layout = {'name':'breadthfirst', 'directed':True},
style={'width': '400px', 'height': '500px'}
)
])
#app.callback(Output('cytoscape-tapNodeData-output', 'children'),
Input('cytoscape-event-callbacks-2', 'tapNodeData'))
def displayTapNodeData(data):
if data:
return
app.run_server(debug=True)
I add the necessary callback to make the dropdown menu working along with the clicking on the nodes. You need only to manipulate how to extract the data from the list edges and nodes in the callback function, and it will be pure python problem, and you can use directly the edges and nodes list inside the callback function without passing them as parameters.
import dash
import dash_cytoscape as cyto
import dash_html_components as html
import dash_core_components as dcc
from dash.dependencies import Input, Output
app = dash.Dash(__name__)
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
nodes = [
{
'data': {'id': short, 'label': label},
}
for short, label in (
('la', 'Los Angeles'),
('nyc', 'New York'),
('to', 'Toronto'),
('mtl', 'Montreal'),
('van', 'Vancouver'),
('chi', 'Chicago'),
('bos', 'Boston'),
('hou', 'Houston')
)
]
edges = [
{'data': {'source': source, 'target': target}}
for source, target in (
('van', 'la'),
('la', 'chi'),
('hou', 'chi'),
('to', 'mtl'),
('mtl', 'bos'),
('nyc', 'bos'),
('to', 'hou'),
('to', 'nyc'),
('la', 'nyc'),
('nyc', 'bos')
)
]
default_stylesheet = [
{
'selector': 'node',
'style': {
'background-color': '#BFD7B5',
'label': 'data(label)'
}
}
]
app.layout = html.Div([
cyto.Cytoscape(
id='cytoscape',
layout={'name':'breadthfirst','directed':True},
elements=edges+nodes,
stylesheet=default_stylesheet,
style={'width': '100%', 'height': '450px'}
),
html.Div([
dcc.Dropdown(['predecessors', 'successors', 'connected'], 'predecessors', id='cyto-dropdown')
]),
html.Div(id='my-output'),
])
#app.callback(Output('my-output', 'children'),
[Input('cyto-dropdown', 'value'),
Input('cytoscape', 'tapNodeData')])
def displayTapNodeData(value, data):
if data:
if value == 'successors':
return "The successor node(s): " + data['id']
elif value == 'predecessors':
return "The predecessor node(s) " + data['id']
elif value == 'connected':
return "The connected node(s): " + data['id']
if __name__ == '__main__':
app.run_server(debug=True, use_reloader=False)
I want to get from a call back a DF(DataFrame) and the figure for that same DF, but I want to show each one individually.
I will take this example posted by #Philippe in this link just to have something to work with and give some ideas:
import dash
import dash_core_components as dcc
import dash_table as dt
import dash_html_components as html
from dash.dependencies import Output, Input
from dash.exceptions import PreventUpdate
import plotly.graph_objs as go
sample_data = {
'series': {
'data': [
{'title': 'Game of Thrones', 'score': 9.5},
{'title': 'Stranger Things', 'score': 8.9},
{'title': 'Vikings', 'score': 8.6}
],
'style': {
'backgroundColor': '#ff998a'
}
},
'movies': {
'data': [
{'title': 'Rambo', 'score': 7.7},
{'title': 'The Terminator', 'score': 8.0},
{'title': 'Alien', 'score': 8.5}
],
'style': {
'backgroundColor': '#fff289'
}
}
}
app = dash.Dash(__name__)
app.layout = html.Div([
html.H1('Multi output example'),
dcc.Dropdown(id='data-dropdown', options=[
{'label': 'Movies', 'value': 'movies'},
{'label': 'Series', 'value': 'series'}
], value='movies'),
html.Div([
dcc.Graph(id='graph'),
dt.DataTable(id='data-table', columns=[
{'name': 'Title', 'id': 'title'},
{'name': 'Score', 'id': 'score'}
])
])
], id='container')
#app.callback([
Output('graph', 'figure'),
Output('data-table', 'data'),
Output('data-table', 'columns'),
Output('container', 'style')
], [Input('data-dropdown', 'value')])
def multi_output(value):
if value is None:
raise PreventUpdate
selected = sample_data[value]
data = selected['data']
columns = [
{'name': k.capitalize(), 'id': k}
for k in data[0].keys()
]
figure = go.Figure(
data=[
go.Bar(x=[x['score']], text=x['title'], name=x['title'])
for x in data
]
)
return figure, data, columns, selected['style']
if __name__ == '__main__':
app.run_server()
In the end a results showing the fig and data of the DataFrame is shown
like this.
However, I want to first show the figure. Then I want to use the data from the DF created in the callback to do more calculations and finally display those calculations using a submit button you click on it.
Is this possible?
What I have done so far is using two different callbacks with kind of the same script, but I was wondering if I can used just one callback a save some repetition in the code.
I hope my question is clear, and thank you in advance!
I found a solution!I used dcc.store here some references if someone need it in the future: https://dash.plotly.com/dash-core-components/store
My line code was this one:
dcc.Store(id='store-data', data=[], storage_type='memory'),
Taking from https://www.youtube.com/watch?v=dLykSQNIM1E. Great video created by Youtube Channel: Charming Data
I am writing a dash app with following inputs like below:-
So far I've written the code as below:-
from dash import Dash, dcc, html, Input, Output, dash_table
import dash
from dash.dependencies import Input, Output, State
import dash
import pandas as pd
import dash_bootstrap_components as dbc
import io
import base64
import dash_renderer
def parse_contents(contents, filename):
# content_type, content_string = contents.split(',')
content_type, content_string = contents.split(',')
decoded = base64.b64decode(content_string)
df1 = pd.read_excel(io.BytesIO(decoded), sheet_name='Sheet1')
df2 = pd.read_excel(io.BytesIO(decoded), sheet_name='Sheet2')
return df1, df2
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.layout = dbc.Container([
dbc.Row(
dbc.Col(html.H1("Container Vulnerability Risk Rating Calculator",
className='text-center text-primary'),
width=12)
),
dbc.Row([
dcc.Upload(
id='upload-data',
children=html.Div([
'Drag and Drop or ',
html.A('Select Files')
]),
style={
'width': '30%',
'height': '40px',
'lineHeight': '40px',
'borderWidth': '1px',
'borderStyle': 'dashed',
'borderRadius': '5px',
'textAlign': 'center',
'margin': '0px'
},
multiple=False
)]
),
dbc.Row([
dbc.Col([
dash_table.DataTable(
id='no-dropdown',
fill_width=False,
columns=[
{'id': 'Microservices', 'name': 'Microservices'}
],
css=[ {"selector": ".Select-menu-outer", "rule": "display : block !important"} ],
style_cell={'textAlign': 'left'},
editable=False,
)
], width=5
),
dbc.Col([
dash_table.DataTable(
id='with-dropdown',
fill_width=False,
css=[ {"selector": ".Select-menu-outer", "rule": "display : block !important"} ],
# style_cell={'textAlign': 'left'},
columns=[
{'id': 'Hosting Environment', 'name': 'Hosting Environment', 'presentation': 'dropdown'},
{'id': 'Complexities', 'name': 'Complexities', 'presentation': 'dropdown'},
{'id': 'Criticality', 'name': 'Criticality', 'presentation': 'dropdown'}
],
editable=False,
)
], width=5
)
]
)
], fluid=True
)
#app.callback(
[
Output('no-dropdown', "data"),
Output('with-dropdown', 'dropdown'),
Output('with-dropdown', 'data')
],
Input('upload-data', 'contents'),
Input('upload-data', 'filename')
)
def load_data(contents, filename):
if contents is not None:
# contents = contents[0]
dff1, dff2 = parse_contents(contents, filename)
dropdown={
'Hosting Environment': {
'options': [
{'label': i, 'value': i} for i in dff2['Hosting Environment']
]
},
'Complexities': {
'options': [
{'label': i, 'value': i} for i in dff2['Complexities']
]
},
'Criticality': {
'options': [
{'label': i, 'value': i} for i in dff2['Criticality']
]
}
}
# print(dff['Hosting Environment'].unique())
return dff1['Microservices'].to_frame().to_dict('records'), dropdown, dff2[['Hosting Environment', 'Complexities', 'Criticality']].to_dict('records')
else:
# print(type([{}]))
return [{}], {}, [{}]
if __name__ == '__main__':
app.run_server(debug=True)
This program renders the Layout where the Microservices column renders fine as it has to be a static column but "Hosting Environment" and other columns highlighted in Yellow, should display a dropdown so that user can select various options.
I first thought that it's due to a bug in Bootstrap, which is well documented. but even after including the workaround code, this still doesn't work.
Any help would be greatly appreciated.
I am trying to build a dashboard where user can choose a pandas dataframe from the dropdown. Also they can search, sort, see the summary and download the data.
I have designed the dropdown many with the file names. Also added the dash.DataTable component. But I am not able to call the dataframe based on the value selected from dropdown.
Code:
import dash
from dash.dependencies import Input, Output
from dash import dash_table
import dash_core_components as dcc
import dash_html_components as html
import pandas as pd
#df = pd.read_csv('data/chronos.csv')
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Dropdown(
id='demo-dropdown',
options=[
{'label': 'Chronos_data', 'value': 'chronos.csv'},
{'label': 'CN_data', 'value': 'cn.csv'},
{'label': 'Expression_data', 'value': 'expression.csv'}
],
value='dataset'
),
html.Div(id='dd-output-container'),
dash_table.DataTable(
id='datatable-interactivity',
columns=[
{"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns
],
data=df.to_dict('records'),
editable=True,
filter_action="native",
sort_action="native",
sort_mode="multi",
column_selectable="single",
row_selectable="multi",
row_deletable=True,
selected_columns=[],
selected_rows=[],
page_action="native",
page_current= 0,
page_size= 15,
export_format='xlsx',
export_headers='display',
merge_duplicate_headers=True
),
html.Div(id='datatable-interactivity-container')
])
#app.callback(
Output('datatable-interactivity', 'data'),
[Input('demo-dropdown', 'value')]
)
def update_output(dropdown_val):
df_data = pd.read_csv('data/'+dropdown_val)
return df_data
#app.callback(
Output('datatable-interactivity', 'style_data_conditional'),
[Input('datatable-interactivity', 'selected_columns')]
)
def update_styles(selected_columns):
return [{
'if': { 'column_id': i },
'background_color': '#D2F3FF'
} for i in selected_columns]
if __name__ == '__main__':
app.run_server(debug=True)
Error: line 27, in <module>
{"name": i, "id": i, "deletable": True, "selectable": True} for i in df.columns
NameError: name 'df' is not defined
Thanks in advance.
Got the answer.
#app.callback(
Output('datatable-interactivity', 'data'),
Output('datatable-interactivity', 'columns'),
[Input('demo-dropdown', 'value')]
)
def update_output(dropdown_val):
df_data = pd.read_csv('data/'+dropdown_val)
return df_data,
[{"name": i, "id": i, "deletable": True, "selectable": True} for i in df_data.columns]