duplicate callback outputs dash figure - python

How can I process when I have 2 callbacks functions with the same output (in that case : a graph) knowing that the first callback function returns a graph and a slider, whereas the input of 2nd callback function is the value of the new slider (created thanks to the first slider ) and returns also a graph (by adding new traces on the old traces)
The code is like that :
# Create Div to place a conditionally visible element inside
myslider = html.Div(
id='slider-container',
children=[
# Create a slider to hide/show
dcc.Slider(0,5,
step=1,
value=0,
id="newslider"
)
],
hidden=True,
)
mygraph = html.Div(dcc.Graph(id="graph", figure=go.Figure(go.Scattergeo())))
mydropdown = html.Div(dcc.Dropdown(['NYC', 'MTL', 'SF'], id="dropdown",
multi=True,
clearable=False))
layout = dbc.Container([mydropdown, mygraph, myslider,html.Div(id='slider-output-container',hidden=True)])
#app.callback(Output(component_id='graph', component_property='figure'),
Output(component_id='newslider', component_property='max'),
Output("newslider", "marks"),
Output(component_id='slider-container', component_property='hidden'),
Input(component_id='dropdown', component_property='value'),
Input(component_id='timeslider', component_property='value'),
State(component_id='newslider', component_property='max'),
State("newslider", "marks"),
prevent_initial_call=True
)
def create_graph_and_slider(dropdown,value,maxi,marks):
#created the initial traces of the graph associated to the newslider thanks to the value of dropdown
return fig, maxi, marks, False
#app.callback(Output(component_id='slider-output-container', component_property='children'),
Output(component_id='slider-output-container', component_property='hidden'),
Output(component_id='graph', component_property='figure'),
Input(component_id='newslider', component_property='value'),
prevent_initiall_call=True
)
def update_graph_from_extrapolation_slider(value):
#add new traces in the graph thanks to the value of new slider
return 'You have selected "{}"'.format(value), False, fig

Related

How do I edit a cell in flet's DataTable?

Flet's DataTable has a show_edit_icon property, but I don't know how do something when the icon is pressed.
This is an example code:
import flet as ft
def main(page: ft.Page):
page.add(
ft.DataTable(
columns=[
ft.DataColumn(ft.Text("First name")),
ft.DataColumn(ft.Text("Last name")),
],
rows=[
ft.DataRow(
cells=[
ft.DataCell(ft.Text("John"), show_edit_icon=True),
ft.DataCell(ft.Text("Smith")),
],
),
],
),
)
ft.app(target=main, view=ft.WEB_BROWSER)
I see the edit icon, but how do I connect it to some function that receives the cell that is being edited?
As per the doccumentation, In FLET data table, show_edit_icon This will only enable you to see the cell's icon. nonetheless, You must create a new function and connect it to the cell on on_tap functionality.
Note:
Add property on_tap to the the cell
implement a new function
Update the page after change inside the new function
import flet as ft
def main(page: ft.Page):
# this is the function that controls the value of the cell
# returns value on tap
def updateOnTap(e):
e.control.content.value = "Hello John"
page.update()
page.add(
ft.DataTable(
columns=[
ft.DataColumn(ft.Text("First name")),
ft.DataColumn(ft.Text("Last name")),
],
rows=[
ft.DataRow(
cells=[
ft.DataCell(ft.Text("John"), show_edit_icon=True, on_tap=updateOnTap),
ft.DataCell(ft.Text("Smith")),
],
),
],
),
)
ft.app(target=main, view=ft.WEB_BROWSER)

Updating graphs with callback in dash plotly

I've already searched everywhere but can't find a way to build a callback to update my graphs in real time properly, can someone give me advices?
The aim is to receive the data through sensors with arduino, but for testing i'm creating random values to plot.
Here is the rep: https://github.com/Gugarauj07/RacingTelemetry_Visualization
This is how i initialy plot the graphs:
graph_temperature = go.Figure(layout={"template": "plotly_dark"})
graph_temperature.add_trace(
go.Scatter(x=df["tempo"], y=df["temp_obj"], name="temp_obj", mode="lines", line=dict(color="#F6511D")))
graph_temperature.add_trace(
go.Scatter(x=df["tempo"], y=df["temp_amb"], name="temp_amb", mode="lines", line=dict(color="#FFB400")))
graph_temperature.update_layout(yaxis_title="Temperatura CVT", margin=dict(l=5, r=5, t=5, b=5), autosize=True,
height=150)
How should i program my callback to update this types of graphs, and not losing the layout?
#app.callback(
[
Output('graph_temperature', 'figure'),
# Output('graph_velocidade', 'figure'),
# Output('graph_RPM', 'figure'),
# Output('graph_ACC', 'figure'),
# Output('graph_laps', 'figure'),
],
Input('interval-component', 'n_intervals')
)
def update_graphs(num):
if num == 0:
raise PreventUpdate
else:
graph_temperature = {
}

Callback Error updating figure in Plotly Dash - Dropdown and Output Figure

so today, I'm trying to create a simple dahsboard with data from multiple dataframes. I use the dropdown to select the dataframe to show in the plot. However, when I run this code, I got callback error in the web page says
Callback error updating loglog.figure
Traceback (most recent call last):
File "C:\Users\nahar\AppData\Local\Temp/ipykernel_1556/982666652.py", line 63, in build_graph
TypeError: string indices must be integers
I don't understand why this occurs, here is the code
logs = ['CALI','RDEP','GR','RHOB','NPHI','SP','DTC']
colors = ['black','firebrick','green','mediumaquamarine','royalblue','goldenrod','lightcoral']
log_cols = np.arange(1,8)
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.SANDSTONE], meta_tags=[
{"name": "viewport", "content": "width=device-width, initial-scale=1"}
])
server = app.server
app.config.suppress_callback_exceptions = True
app.layout = dbc.Container([
dbc.Row([
dbc.Col(html.H1('FORCE 2020 Well Log Challange Dashboard',
className='text-center mb-4'),
width=12)
]),
dbc.Row([
dbc.Col([
dcc.Dropdown(id='droplog',
options=[
{'label':'15/9-13','value':'well1'},
{'label':'15/9-15','value':'well2'},
{'label':'15/9-17','value':'well3'},
{'label':'16/1-2','value':'well4'},
{'label':'16/1-6 A','value':'well5'},
{'label':'16/10-1','value':'well6'},
{'label':'16/10-2','value':'well7'},
{'label':'16/10-3','value':'well8'},
{'label':'16/10-5','value':'well9'},
{'label':'16/11-1 ST3','value':'well10'},
{'label':'16/2-11 A','value':'well11'},
{'label':'16/2-16','value':'well12'}
], multi=False, value='well1'),
dcc.Graph(id='loglog',figure={})
])
]),
dbc.Row([
])
])
#app.callback(
Output(component_id='loglog',component_property='figure'),
[Input(component_id='droplog',component_property='value')]
)
def build_graph(plot_chosen):
logplot = make_subplots(rows=1, cols=len(logs), shared_yaxes=True)
for i in range (len(logs)):
if i == 1:
logplot.add_trace(go.Scatter(x=plot_chosen[logs[i]], y=plot_chosen['DEPTH_MD'],
name=logs[i], line_color=colors[i]),row=1, col=log_cols[i])
logplot.update_xaxes(type='log',row=1, col=log_cols[i], title_text=logs[i],
tickfont_size=12, linecolor='#585858')
else:
logplot.add_trace(go.Scatter(x=plot_chosen[logs[i]], y=plot_chosen['DEPTH_MD'],
name=logs[i], line_color=colors[i]),row=1, col=log_cols[i])
logplot.update_xaxes(col=log_cols[i], title_text=logs[i], linecolor='#585858')
logplot.update_xaxes(showline=True, linewidth=2, linecolor='black', mirror=True, ticks='inside', tickangle= 0)
logplot.update_yaxes(tickmode='linear', tick0=0,dtick=250, showline=True, linewidth=2, linecolor='black',
mirror=True, ticks='outside')
logplot.update_yaxes(row=1, col=1, autorange='reversed')
logplot.update_layout(height=750, width=1200, showlegend=False)
logplot.update_layout(plot_bgcolor = "rgba(0,0,0,0)", paper_bgcolor = "rgba(0,0,0,0)")
return logplot
if __name__=='__main__':
app.run_server(debug=True,use_reloader=False)
and the input data used is in the form of many dataframes, one of which is like this
for well 1
I tried to run defined function only, which build_graph, and it worked like a charm. The result of figure is shown here
I think I know what the problem is: the variable plot_chosen which is the argument in the function build_graph is a string. As a result you can not type y=plot_chosen['DEPTH_MD']. Although after choosing 15/9-13 on the Dropdown menu it has a value of well1, it does not represent the dataframe but a simple string. Try creating for example a dictionary with the dataframes
dataframes = {'well1': well1, 'well2': well2, ...}
and then choose the appropriate DataFrame from the dictionary.
So for example when the user chooses 15/9-13 on the dropdown you will get plot_chosen='well1' and you can simply get the dataframe well1 by using dataframes[plot_chosen].

Dashboard with DASH - Argument issues dcc.graph()

I'm trying to create a dashboard in Pycharm using dash. Here is the error I keep receiving,
html.Div(dcc.Graph(id='line-plot')),
TypeError: Graph() takes no arguments
And below is a snippet of my code where the error is being found (bottom of code). This code ran fine and I was about to populate the dashboard without receiving any errors inside IBM's python environment. I'm assuming I have to tweak something
# TASK 3 - UPDATE LAYOUT COMPONENETS
# html.H1 tag for title , style, and overall font size
# html.Div & dcc.Input() tag to set inputs of the dashboard
# Update output componenent 2nd html.Div to layout the graph dcc.Graph()
app.layout = html.Div(children=[html.H1('Airline Performance Dashboard',
style={'textAlign': 'center', 'color': '#503D36',
'font-size': 40}),
html.Div(["Input Year: ", dcc.Input(id='input-year', value='2010',
type='number',
style={'height': '50px', 'font-size': 35}), ],
style={'font-size': 40}),
html.Br(),
html.Br(),
html.Div(dcc.Graph(id='line-plot')),
])
Here is the rest of the code,
# TASK 4 - ADD APPLICATION CALL BACK FUNCTION and outputs / inputs
# add callback decorator
#app.callback(Output(component_id='line-plot', component_property='figure'),
Input(component_id='input-year', component_property='value'))
# Add computation to callback function and return graph
def get_graph(entered_year):
# Select 2019 data
df = airline_data[airline_data['Year'] == int(entered_year)]
# Group the data by Month and compute average over arrival delay time.
line_data = df.groupby('Month')['ArrDelay'].mean().reset_index()
# TASK 5 - UPDATE CALL BACK FUNCTION go.Figure(data=) and update fig.update_layout()
fig = go.Figure(
data=go.Scatter(x=line_data['Month'], y=line_data['ArrDelay'], mode='lines', marker=dict(color='green')))
fig.update_layout(title='Month vs Average Flight Delay Time', xaxis_title='Month', yaxis_title='ArrDelay')
return fig
# Run the app
if __name__ == '__main__':
app.run_server()
Its safe to say I need an adult.
have added import and simulation of data frame
all other code runs without issue on plotly 5.1.0
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import plotly.graph_objects as go
from jupyter_dash import JupyterDash
import numpy as np
app = JupyterDash(__name__)
# simulate data...
dr = pd.date_range("1-jan-2010", freq="W", periods=200)
airline_data = pd.DataFrame({"Year":dr.year, "Month":dr.month, "ArrDelay":np.random.uniform(2,5,len(dr))})
# TASK 3 - UPDATE LAYOUT COMPONENETS
# html.H1 tag for title , style, and overall font size
# html.Div & dcc.Input() tag to set inputs of the dashboard
# Update output componenent 2nd html.Div to layout the graph dcc.Graph()
app.layout = html.Div(children=[html.H1('Airline Performance Dashboard',
style={'textAlign': 'center', 'color': '#503D36',
'font-size': 40}),
html.Div(["Input Year: ", dcc.Input(id='input-year', value='2010',
type='number',
style={'height': '50px', 'font-size': 35}), ],
style={'font-size': 40}),
html.Br(),
html.Br(),
html.Div(dcc.Graph(id='line-plot')),
])
# TASK 4 - ADD APPLICATION CALL BACK FUNCTION and outputs / inputs
# add callback decorator
#app.callback(Output(component_id='line-plot', component_property='figure'),
Input(component_id='input-year', component_property='value'))
# Add computation to callback function and return graph
def get_graph(entered_year):
# Select 2019 data
df = airline_data[airline_data['Year'] == int(entered_year)]
# Group the data by Month and compute average over arrival delay time.
line_data = df.groupby('Month')['ArrDelay'].mean().reset_index()
# TASK 5 - UPDATE CALL BACK FUNCTION go.Figure(data=) and update fig.update_layout()
fig = go.Figure(
data=go.Scatter(x=line_data['Month'], y=line_data['ArrDelay'], mode='lines', marker=dict(color='green')))
fig.update_layout(title='Month vs Average Flight Delay Time', xaxis_title='Month', yaxis_title='ArrDelay')
return fig
app.run_server(mode="inline")

Dash(Python) - can't update Slider's values based on input from another Slider

I've started learning Dash(after using R-Shiny for ~3months). During which I've tried to make an app, which will have two Sliders, one of whose values(min, max, step) are fixed and values of the other Slider will be updated based on the input from first Slider. And I couldn't update values of second Slider.
Here's what I've done and tried:
from dash import Dash
import dash_html_components as dash_html
import dash_core_components as dash_core
from dash.dependencies import Input, Output
from flask import Flask
# initiate the dash app with Flask server
app = Dash(__name__, server=Flask(__name__))
# code the ui now
app.layout = dash_html.Div(children=[
dash_core.Slider(id="first_slider",
min=10, max=110, value=10, step=10,
marks={i : '{}'.format(i) for i in range(10,110,10)},
# marks={i : 'Level {}'.format(i) for i in range(10,110,10)}
),
dash_html.Hr(), dash_html.Hr(),
# second slider
dash_core.Slider(id="second_slider"),
# # dash_html.Hr(),
# print values from both sliders
dash_html.Div(id="display_selected_values"),
])
# take the input from first and update second slider
#app.callback(Output(component_id='second_slider', component_property=['min','max']),
# component_property='children'),
# component_property='value'),
[Input(component_id='first_slider', component_property='value')])
def print_the_value_from_slider(value_from_slider):
# update the values of second slider. ex: if input is 10, second slider will have 11 to 20
# return value_from_slider
return list((value_from_slider+1, value_from_slider+1+10))
# #app.callback(Output(component_id="second_slider", component_property='options'),
# [Input(component_id='second_slider', component_property='value')])
# def fill_second_slider(value_from_first_slider):
# return range(value_from_first_slider+1, value_from_first_slider+1+10, 1)
# #app.callback(Output('display_selected_values', 'children'),
# [Input('first_slider', 'value'),
# Input('second_slider', 'value')])
# def set_display_children(first_input, second_input):
# return '{} from {}s range'.format(second_input, first_input)
if __name__ == '__main__':
app.run_server(debug=True)
and the error is:
dash.exceptions.NonExistentPropException:
Attempting to assign a callback with
the property "['min', 'max']" but the component
"second_slider" doesn't have "['min', 'max']" as a property.
Here are the available properties in "second_slider":
['id', 'marks', 'value', 'className', 'disabled', 'dots', 'included', 'min', 'max', 'tooltip', 'step', 'vertical', 'updatemode', 'loading_state']
But, Slider does have min and max properties and they are listed in error too. I don't know what I'm doing wrong. But, the second slider is not getting updated.
The slider does have the min and max props, but you are trying to set a single prop [min, max] which does not exist. You need two outputs on your callback, one to each prop.
#app.callback([Output(component_id='second_slider', component_property='min'),
Output(component_id='second_slider', component_property='max')]
[Input(component_id='first_slider', component_property='value')])
That should work.

Categories