Access the input variables using a formula in call back function

Hi,
I am new to dash and trying to create an app that calculates the number of needed rooms in a department given various variables such as # of visitors, processing times, working hours… . So I created a layout and had several sliding bars to input those variables. I have a barchart that shows the expected number of rooms (as an output). My only problem, I am not able to access the input variables and put them into an equation that calculates the number of needed rooms. In the code bellow, you will find Equation 1 and Equation 2.
For both equations I should multiply 2 or more of the values of the sliding bars but I do not know how to access them. What piece of code can I use to access the variables and multiply them?

the call back should update the figure that is called NumRooms considering all those input variables

@app.callback(
Output(‘NumRooms’, ‘figure’),
[Input(‘Virtual Visits %’, ‘value’),
Input(‘In Person Visits (%)’, ‘value’),
Input(‘Targeted Utilization (%)’, ‘value’),
Input(‘NumRooms’, ‘value’),
Input(‘my-daq-knob’, ‘value’)])

This is the function, and the formula should be located in XAxis and Y Axis

def update_graph():
XAxis= Equation1

YAxis=Equation2
figure={
        'data': [
            {'x': ['KeyRooms', 'Virtual Rooms'], 'y': [XAxis, YAxis], 'type': 'bar', 'name': 'Key Rooms'},
        ],
        'layout': {
            'paper_bgcolor': colors['background'],
            'font': {
                'color': colors['text2']
            }
        }
    }

return figure

It seems that you have 5 Inputs fot the callback. In this case you would then write 5 arguments for the update_graph:

@app.callback(
Output(‘NumRooms’, ‘figure’),
[Input(‘Virtual Visits %’, ‘value’),
Input(‘In Person Visits (%)’, ‘value’),
Input(‘Targeted Utilization (%)’, ‘value’),
Input(‘NumRooms’, ‘value’),
Input(‘my-daq-knob’, ‘value’)])
def update_graph(virtual_visits, visits, target, nrooms, knobval):
    # create a figure using the arguments (virtual_visits etc.)
    return figure

Does this help you?

That’s exactly where I need that help. How to do that?

This is my full code. You will see several sliding bards which indicate the inputs. Then I have a graph where I want to results. But I am not being able to access the right variables…How can the update function understand which one is input 1 and input 2…? Can you write me an example of the syntax of this? Thank you very much for the reply

import dash
import dash_core_components as dcc #used for graphs
import dash_html_components as html
import dash_daq as daq
from dash.dependencies import Output,Input,State #deal with outputs inputs
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import dash
import dash_daq as daq
import dash_core_components as dcc

#change the data function
def generatetable():
return [1, 4, 2]

Datax=[1,2,3]
Datay=[2, 4, 5]

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(name, external_stylesheets=external_stylesheets)

colors = {
‘background’: ‘#ffffff’,
‘text’: ‘#7FDBFF’,
‘text2’:’#646464
}
#Layout
app.layout = html.Div(style={‘backgroundColor’: colors[‘background’]}, children=[
html.H1(
children=‘Interactive Planning Dashboard’,
style={
‘textAlign’: ‘center’,
‘color’: colors[‘text’] }),

 # sliders bar code for max num of patients  
html.Div('Max Number of Patients',style={'padding': 32}),
daq.Slider(
id='NumPatients',
min=0,
max=100,
value=50,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),       

# sliders bar for in patient visits  
html.Div('In Person Visits (%)',style={'padding': 32}),
daq.Slider(
id='Visits',
min=0,
max=100,
value=80,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),  


# sliders bar for virtual visits
html.Div('Virtual Visits %',style={'padding': 32}),
daq.Slider(
id='Virtual',
min=0,
max=100,
value=20,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),  



# sliders bar for Duration of visit
html.Div('Duration of visit (min)',style={'padding': 32}),
daq.Slider(
id='Duration',
min=0,
max=50,
value=20,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),    

# Hours operation  
html.Div('Hours of Operations',style={'padding': 32}),
daq.Slider(
id='Hours',
min=0,
max=24,
value=8,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),   

# choices
html.Div('Use of Telebooth',style={'padding': 32}),
dcc.Dropdown(
options=[
    {'label': 'Yes', 'value': 'Y'},
    {'label': 'No', 'value': 'N'},
   
],
value='Y'),  


# spedometer for utilization  
html.Div('Targeted Utilization (%)',style={'padding': 32}),

daq.Knob(
  id='my-daq-knob',
  min=0,
  max=100,
  value=80
),



# start of graph
dcc.Graph(id='NumRooms')
#end graph

])

@app.callback(
Output(‘NumRooms’, ‘figure’),
[Input(‘Max Number of Patients’, ‘value’),
Input(‘In Person Visits (%)’, ‘value’),
Input(‘Targeted Utilization (%)’, ‘value’),
Input(‘Duration of visit (min)’, ‘value’),
Input(‘Hours of Operations’, ‘value’)])

def update_graph(Input1,Input2,Input3,Input4,Input5 ):
XAxis= (Input1*Input4)/Input5
YAxis=Input2
figure={
‘data’: [
{‘x’: [‘KeyRooms’, ‘Virtual Rooms’], ‘y’: [XAxis, YAxis], ‘type’: ‘bar’, ‘name’: ‘Key Rooms’},
],
‘layout’: {
‘paper_bgcolor’: colors[‘background’],
‘font’: {
‘color’: colors[‘text2’]
}
}
}

return figure

if name == ‘main’:
app.run_server(debug=False)

I think the problem is that you are accessing Divs instead of the sliders. You are passing to the callback:

Input(‘Max Number of Patients’, ‘value’)

where Max Number of Patients is the Div id, I think this should be:

Input(‘NumPatients’, ‘value’)

The same for the others.

2 Likes

Well, this seems to be what caused the app not to work, so thanks @danielT43. I have a question here, does the dash read the variables in order as you define them in the callback? In the example below, input1 in the update function will be associated to Duration, and input2 is Visits. Am I getting it right?

@app.callback(
Output(‘NumRooms’, ‘figure’),
[Input(‘Duration’, ‘value’),
Input(‘Visits’, ‘value’),
Input(‘Uti’, ‘value’),
Input(‘Duration’, ‘value’),
Input(‘Hours’, ‘value’)])

def update_graph(Input1,Input2,Input3,Input4,Input5 ):

My second question is that I have an input as a select variable. What is the right syntax to say in the update function, if the label was Yes then use Equation 1, if No use equation 2. Would you mind please writing an example?

html.Div('Use of Telebooth',style={'padding': 32}),
dcc.Dropdown(
options=[
    {'label': 'Yes', 'value': 'Y'},
    {'label': 'No', 'value': 'N'},
   
],
value='Y'),
  1. Yes, the order of Inputs (and States) passed to the decorated function is the same as what you give as arguments to the @app.callback().

  2. The logic is very simple. You need to know the component id, and then you need the property inside the component that you want to access. So, for example the dcc.Dropdown has properties (read “Dropdown Properties” at the end of the page):

  • id
  • className
  • value

You want to access the value property since it contains the selected value, as explained in the dcc.Dropdown documentation. So, if you have this on your layout

dcc.Dropdown(
    id='my-dropdown',
    options=[
        {'label': 'Yes', 'value': 'Y'},
        {'label': 'No', 'value': 'N'},  
    ],
    value='Y')

you need to create callback like this

@app.callback(
Output('some-other-component',  'some-property'),
[Input('my-dropdown', 'value')])
def some_function(val):
    if val == 'Y':
        # value was 'Y', so the label 'Yes' was selected
    else:
        # value was not 'Y'
1 Like

Many thanks! It is working well!

Hi, can I have one more question, please?
How can I split up the layout into two halves; the left side includes all input variables (bars, dropdownlinst…), the right side includes all figures (output variables). I am new to Dash and not sure how to change the layout. This is my code.

import dash
import dash_core_components as dcc #used for graphs
import dash_html_components as html
import dash_daq as daq
from dash.dependencies import Output,Input,State #deal with outputs inputs
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import dash
import dash_daq as daq
import dash_core_components as dcc

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(name, external_stylesheets=external_stylesheets)

colors = {
‘background’: ‘#ffffff’,
‘text’: ‘#7FDBFF’,
‘text2’:’#646464
}
#Layout
app.layout = html.Div(style={‘backgroundColor’: colors[‘background’]}, children=[
html.H1(
children=‘Interactive Planning Dashboard’,
style={
‘textAlign’: ‘center’,
‘color’: colors[‘text’] }),

html.Div('Number of Patients',style={'padding': 35}),
daq.Slider(
id='Visits',
min=0,
max=500,
value=50,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),       

# sliders bar for in patient visits  
html.Div('In Person Visits (%)',style={'padding': 35}),
daq.Slider(
id='VisitsPerson',
min=0,
max=100,
value=80,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),  


html.Div('Virtual Visits %',style={'padding': 35}),
daq.Slider(
id='Virtual',
min=0,
max=100,
value=20,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),  


html.Div('Duration of visit (min)',style={'padding': 35}),
daq.Slider(
id='Duration',
min=0,
max=50,
value=20,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),    

html.Div('Hours of Operations',style={'padding': 35}),
daq.Slider(
id='Hours',
min=0,
max=24,
value=8,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),   

html.Div('Use of Telebooth',style={'padding': 35}),
dcc.Dropdown(
id='dropdown',    
options=[
    {'label': 'Yes', 'value': 'Y'},
    {'label': 'No', 'value': 'N'},
   
],
value='Y'),  

html.Div('Targeted Utilization (%)',style={'padding': 35}),

daq.Knob(
  id='Uti',
  min=0,
  max=100,
  value=80
),



dcc.Graph(id='NumRooms'),

dcc.Graph(id='SF')

])

@app.callback(
Output(‘NumRooms’, ‘figure’),
[Input(‘Duration’, ‘value’),
Input(‘Visits’, ‘value’),
Input(‘Uti’, ‘value’),
Input(‘Hours’, ‘value’),
Input(‘dropdown’, ‘value’),
Input(‘Virtual’, ‘value’)
])

def update_graph(Duration,Visits,Uti,Hours,dropdown,Virtual):

if dropdown =='Y':
    XAxis1= round((Visits*(1-(Virtual/100))*Duration)/(Hours*60*Uti/100))
    XAxis2= round((Visits*(Virtual/100)*Duration)/(Hours*60*Uti/100))
else:
    XAxis1= round((Visits*Duration)/(Hours*60*Uti/100))
    XAxis2= 0

figure={
        'data': [
            {'x': ['KeyRooms', 'Virtual Rooms'], 'y': [XAxis1, XAxis2], 'type': 'bar', 'name': 'Key Rooms'},
        ],
        'layout': {
            'paper_bgcolor': colors['background'],
            'font': {
                'color': colors['text2']
            }
        }
    }

return figure

@app.callback(
Output(‘SF’, ‘figure’),
[Input(‘Duration’, ‘value’),
Input(‘Visits’, ‘value’),
Input(‘Uti’, ‘value’),
Input(‘Hours’, ‘value’),
Input(‘dropdown’, ‘value’),
Input(‘Virtual’, ‘value’)
])

def update_graph2(Duration,Visits,Uti,Hours,dropdown,Virtual):
if dropdown ==‘Y’:
SF1= (round((Visits*(1-(Virtual/100))Duration)/(Hours60Uti/100)))650
SF2= (round((Visits
(Virtual/100)Duration)/(Hours60
Uti/100)))40
else:
SF1= (round((Visits
Duration)/(Hours60Uti/100)))*650
SF2= 0

 figure={
        'data': [
            {'x': ['KeyRooms', 'Virtual Rooms'], 'y': [SF1, SF2], 'type': 'bar', 'name': 'DGSF'},
        ],
        'layout': {
            'paper_bgcolor': colors['background'],
            'font': {
                'color': colors['text2']
            }
        }
    }

 return figure

if name == ‘main’:
app.run_server(debug=False)

Splitting to two halves is something you would accomplish by

  • Putting the two halves into divs, and wrapping them in common div. Something like:

html.Div(
    html.Div(content_left, className='left-side'), html.Div(content_right, className='right-side')
)
  • Then, using CSS to adjust the sizes. So, in ./css/99_my_styles.css (. being your dash application root folder), in the simplest case you would put something like
.left-side{
    width: 400px;
}

.right-side{
    width: 400px;
}

Or: width:50%. Now, making it work well with any screen size & layout is art of its’ own, but this is a good starting point.

Hi @fohrloop
First thanks for the reply! I do not think I am getting this correctly. Especially when it comes to the indexing.
If you are to split the input and output shown bellow into the new layout, would you mind putting them for me in the script as you provided in the last reply? I think I will get it better by seeing it in an example. Also I did not get the following : * Then, using CSS to adjust the sizes. So, in ./css/99_my_styles.css ( . being your dash application root folder), in the simplest case you would put something like

I would appreciate if you use the input and output bellow to show me how this can change now.

#I want to keep the title in the center
app.layout = html.Div(style={‘backgroundColor’: colors[‘background’]}, children=[
html.H1(
children=‘Interactive Planning Dashboard’,
style={
‘textAlign’: ‘center’,
‘color’: colors[‘text’] }),

#This is the input

 # sliders bar code for max num of patients  
html.Div('Number of Patients',style={'padding': 35}),
daq.Slider(
id='Visits',
min=0,
max=500,
value=50,
handleLabel={"showCurrentValue": True,"label": "VALUE"},
step=1),  ])

#This is the output

html.Div(children=’’’
Number of Clinics’’’, style={
‘textAlign’: ‘center’,
‘color’: colors[‘text2’]
}),
# start of graph
dcc.Graph(id=‘NumRooms’),
#end graph
html.Div(children=’’’
Total Space Needed
‘’’, style={
‘textAlign’: ‘center’,
‘color’: colors[‘text2’]
}),
# start of graph
dcc.Graph(id=‘SF’)
#end graph