I am new to Dash and am working on creating a dashboard on multi-objective optimization in Dash plotly. I am creating interactive graphs where if I click on any data point in the scatter plot (f1 vs f2), the slider (x1, x2, x3, x4) should adjust the value. I read about the slider tutorial, but what I need is the reverse of that: clicking on any data point in the scatter plot, the slider values of x1, x2, x3, and x4 should show up.
Here is the code that I am using. Please let me know if it’s feasible in Dash and if yes, what changes in the code I need to make in order to get the desired result.
import base64
import datetime
import io
import dash
from dash.dependencies import Input, Output, State
from dash import Dash, dcc, html, Patch
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import figure
import dash_bootstrap_components as dbc
app = dash.Dash(
__name__,
external_stylesheets=[dbc.themes.BOOTSTRAP],
suppress_callback_exceptions=True,
)
server = app.server
app.layout = html.Div([
html.H1(
children="MOO Visualization",
style={
"fontFamily": "Gill Sans",
"fontWeight": "400",
"textAlign": "center",
},
),
dcc.Upload(
id="upload-data",
children=html.Div(["Drag and Drop or ",
html.A("Select Files")]),
style={
"width": "100",
"height": "60px",
"lineHeight": "60px",
"borderWidth": "1px",
"borderStyle": "dashed",
"borderRadius": "5px",
"textAlign": "center",
"margin": "10px",
},
# Allow multiple files to be uploaded
multiple=True,
),
html.Div([
html.Div([
html.Div(id="graph-container",
style={
'display': 'inline-block',
'width': '60%',
}),
html.Div(
[
html.Div([
html.Label([
"x1",
dcc.Slider(min=0, max=1, step=0.1, id="slider1")
], )
],
),
html.Div([
html.Label([
"x2",
dcc.Slider(min=0, max=1, step=0.1, id="slider2")
], )
],
),
html.Div([
html.Label([
"x3",
dcc.Slider(min=0, max=1, step=0.1, id="slider3")
], )
],
),
html.Div(
[
html.Label([
"x4",
dcc.
Slider(min=0, max=1, step=0.1, id="slider4")
], )
],
)
],
style={
'display': 'inline-block',
'width': '40%',
'padding-top': '4%',
'float': 'right',
'fontSize': '14',
'font-family': 'Arial',
'backgroundColor': '#ffffff'
})
] )
])
])
# File upload function
def parse_data(contents, filename):
content_type, content_string = contents.split(",")
decoded = base64.b64decode(content_string)
try:
if "csv" in filename:
# Assume that the user uploaded a CSV file
df = pd.read_csv(io.StringIO(decoded.decode("utf-8")))
elif "xls" in filename:
# Assume that the user uploaded an excel file
df = pd.read_excel(io.BytesIO(decoded))
except Exception as e:
print(e)
return html.Div(["There was an error processing this file."])
return df
@app.callback(
Output("graph-container", "children"),
#Output("slider1","value"),
#Output("slider2","value"),
#Output("slider3","value"),
#Output("slider4","value"),
[Input("upload-data", "contents"),
Input("upload-data", "filename")],
)
def update_output(contents, filename):
if contents is not None:
contents = contents[0]
filename = filename[0]
df = parse_data(contents, filename)
cols1 = ["f1", "f2"]
cols2 = ["f1", "f2", "f3"]
cols3 = ["f1", "f2", "f3", "f4"]
for c in df.columns:
if c in cols1:
fig = go.Figure(px.scatter(
df,
x=df["f1"],
y=df["f2"],
labels={
"df[f1]": "f1",
"df[f2]": "f2",
},
),
layout=go.Layout(width=50, height=50))
graph = dcc.Graph(figure=fig)
elif c in cols2:
fig = go.Figure(
px.scatter_3d(
df,
x=df["f1"],
y=df["f2"],
z=df["f3"],
labels={
"df[f1]": "f1",
"df[f2]": "f2",
"df[f3]": "f3",
},
))
graph = dcc.Graph(figure=fig)
elif c in cols3:
fig = go.Figure(
px.scatter_3d(
df,
x=df["f1"],
y=df["f2"],
z=df["f3"],
color=df["f4"],
labels={
"df[f1]": "f1",
"df[f2]": "f2",
"df[f3]": "f3",
"df[f4]": "f4",
},
))
graph = dcc.Graph(figure=fig)
return graph
#@app.callback(
# Output(),
# Input()
#)
#def slider_output(graph_point):
# return slider1, slider2, slider3, slider4
if __name__ == "__main__":
app.run_server(debug=True)
Thank you.