One Graph depends on multiple sliders (Problem Resolved)

Hi,

I need some help with my code.

I have multiple sliders:

dcc.Slider(
id=‘dt-slider’,
min=0.6,
max=1.0,
step=0.1,
marks={i: ‘{}’.format(float(i)) for i in range(5)},
value=1.0,
),
html.Br(),
html.Label(id=‘j-update’),
dcc.Slider(
id=‘j-slider’,
marks={i * 30: ‘{}’.format(i * 30) for i in range(11)},
min=0,
max=300,
step=1,
value=80,
),

One graph:

dcc.Graph(
id=‘two-sources-graph’
),

And two callbacks:

@app.callback([Output(‘two-sources-graph’, ‘figure’),
** Output(‘dt-update’, ‘children’)],**
** [Input(‘dt-slider’, ‘value’)])**
def display_value(value):
global dt_global
dt_global = value
children = 'dt = ’ + str(float(value))
figure = update_chart()
return figure, children

@app.callback([Output(‘two-sources-graph’, ‘figure’),
** Output(‘j-update’, ‘children’)],**
** [Input(‘j-slider’, ‘value’)])**
def display_value(value):
global j_global
j_global = value
children = 'J = ’ + str(value)
figure = update_chart()
return figure, children

I need to update the graph based on sliders values when they are changed.

I know it does not accept the same output id on different callbacks but I need the value of all sliders to compute the graph
values when they change their values.

Is there any way to do it?

Thanks,

Hola @Izanotto,

to update your graph what you need is a callback with multiple inputs and one output. Simple example:

@app.callback(
    Output('map-graph', 'figure'),
    [Input('Slide1', 'value'),
    Input('Slide2', 'value')])

def map_selection(valorslide1, valorslide2):
    map_aux = map_aux[map_aux['Critério1']==valorslide1]
    map_aux = map_aux[map_aux['Critério2']==valorslide2]
    trace=...
    layout=...
    return {'data': trace, 'layout': layout}

(Espero que ajude!) :slight_smile:

Hi Cecilia,

Thanks for your help, but I think it is better to show the entire code here.

As you can see the slider updates its own label value,. I want to update also the graph when its value is changed.
This code will only update the graph when the button is clicked. I would like not use the button, only the sliders to update the
graph when its value changes.

If you have any solution I apreciate.

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
from dash.dependencies import Input, Output
import base64

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

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

image_filename = '2source.png'
encoded_image = base64.b64encode(open(image_filename, 'rb').read())

dt_global = 0.0
j_global = 0
n_global = 0
q_global = 0.0
k_global = 0.0
k3_global = 0.0
k4_global = 0.0
k7_global = 0.0
k8_global = 0.0
tc_global = 0

my_dictionary = {
    'Q': [],
    'T': [],
    'N': [],
}

app.layout = html.Div([
    html.Div([
        html.H3(
            children='Two Sources Mini-Model Simulation',
            style={
                'textAlign': 'center',
            }
        ),
        html.Div([
            html.Div([
                html.H2(
                    children='Process Controls',
                    style={
                        'textAlign': 'center',
                    }),
                html.Label('Y max = 250'),
                html.Label(id='dt-update'),
                dcc.Slider(
                    id='dt-slider',
                    min=0.6,
                    max=1.0,
                    step=0.1,
                    marks={i: '{}'.format(float(i)) for i in range(5)},
                    value=1.0,
                ),
                html.Br(),
                html.Label(id='j-update'),
                dcc.Slider(
                    id='j-slider',
                    marks={i * 30: '{}'.format(i * 30) for i in range(11)},
                    min=0,
                    max=300,
                    step=1,
                    value=80,
                ),
                html.Br(),
                html.Label(id='n-update'),
                dcc.Slider(
                    id='n-slider',
                    min=0,
                    max=250,
                    step=1,
                    marks={i * 25: '{}'.format(25 * i) for i in range(11)},
                    value=150,
                ),
                html.Br(),
                html.Label(id='q-update'),
                dcc.Slider(
                    id='q-slider',
                    min=0,
                    max=30,
                    step=1,
                    marks={i * 10: '{}'.format(10 * i) for i in range(4)},
                    value=1,
                ),
                html.Br(),
                html.Label(id='k-update'),
                dcc.Slider(
                    id='k-slider',
                    min=0.0,
                    max=3.0,
                    step=0.01,
                    marks={i: '{}'.format(float(i)) for i in range(4)},
                    value=0.1,
                ),
                html.Br(),
                html.Label(id='k3-update'),
                dcc.Slider(
                    id='k3-slider',
                    min=0,
                    max=0.005,
                    step=0.001,
                    marks={i: '{}'.format(i) for i in range(6)},
                    value=0.002,
                ),
                html.Br(),
                html.Label(id='k4-update'),
                dcc.Slider(
                    id='k4-slider',
                    min=0.0,
                    max=0.005,
                    step=0.001,
                    marks={i * 10: '{}'.format(10 * float(i)) for i in range(5)},
                    value=0.01,
                ),
                html.Br(),
                html.Label(id='k7-update'),
                dcc.Slider(
                    id='k7-slider',
                    min=0.0,
                    max=0.0016,
                    step=0.001,
                    marks={i * 4: '{}'.format(4 * float(i)) for i in range(5)},
                    value=0.0008,
                ),
                html.Br(),
                html.Label(id='k8-update'),
                dcc.Slider(
                    id='k8-slider',
                    min=0.0,
                    max=0.25,
                    step=0.001,
                    marks={i * 10: '{}'.format(10 * float(i)) for i in range(5)},
                    value=0.03,
                ),
                html.Br(),
                html.Label(id='tc-update'),
                dcc.Slider(
                    id='tc-slider',
                    marks={i * 32: '{}'.format(i * 32) for i in range(11)},
                    min=0,
                    max=320,
                    step=1,
                    value=80,
                ),
                html.Br(),
                html.Button('Plot Graph', id='button'),
                dcc.Markdown('''
                #### TC = Critical Time
                The time when humanity develops the knowledge 
                to use fossil fuel. If TC is above 320 it means
                fossil fuels are not used.                
                '''),

                # html.Br(),
                # dcc.Markdown('''
                # #### Quick Test: after TC consider a time of starting chaos (DT)
                # '''),
                # html.Label('New Parameters'),
                # dcc.Slider(
                #     id='dt2-slider',
                #     min=0.0,
                #     max=0.25,
                #     step=0.001,
                #     marks={i * 10: '{}'.format(10 * float(i)) for i in range(5)},
                #     value=0.03,
                # ),
                html.Br(),

            ], className='six columns'),
            html.Div([
                dcc.Graph(
                    id='two-sources-graph'
                ),
                # html.Br(),
                # html.Img(src='2source.png'.format(encoded_image)),
                dcc.Markdown('''
                #### Description
            
                A system of this type uses two energy sources, one renewable, the other nonrenewable. When the nonrenewable source is used up, the growth declines back to a steady state based on the renewable source.
                
                #### Variables
            
                * N = nonrenewable energy source
                * J = steady inflow of energy
                * Q = stored biomass
                * K*JR*Q = part of J that goes into the system
                * K3 = increasing factor of Q
                * K7 = increasing factor of Q
                * K8 = decreasing factor of Q
            
                #### Equations
            
                * DN = -K4*N*Q
                * JR = J/(1 + K*Q)
                * DQ = K7*N*Q + K3*JR*Q - K8*Q
            
                #### Simulation
            
                The graph shows the changes of N (red) and Q (green) over a time period.
                
                #### Examples
            
                A population of microbes which decompose a pile of leaves and the leaves falling from the trees.
                The world economy growing up on both fossil fuels and renewable sources.
            
                #### "What if" Experiments
            
                Think about the renewable and nonrenewable sources of our economy:
                If we find more fuels (N), will our industrial society peak higher or last longer?
                If pollution increases giving us less available clear sun and rain (J), how will this affect the growth and future of the economy?
                '''),

            ], className='six columns'),
        ], className="row"),
    ]),
])


@app.callback(Output('dt-update', 'children'),
              [Input('dt-slider', 'value')])
def display_value(value):
    global dt_global
    dt_global = value
    # calculate_curves()
    return 'dt = ' + str(float(value))


@app.callback(Output('j-update', 'children'),
              [Input('j-slider', 'value')])
def display_value(value):
    global j_global
    j_global = value
    return 'J = ' + str(value)


@app.callback(Output('n-update', 'children'),
              [Input('n-slider', 'value')])
def display_value(value):
    global n_global
    n_global = value
    return 'N = ' + str(value)


@app.callback(Output('q-update', 'children'),
              [Input('q-slider', 'value')])
def display_value(value):
    global q_global
    q_global = value
    return 'Q = ' + str(float(value))


@app.callback(Output('k-update', 'children'),
              [Input('k-slider', 'value')])
def display_value(value):
    global k_global
    k_global = value
    return 'K = ' + str(float(value))


@app.callback(Output('k3-update', 'children'),
              [Input('k3-slider', 'value')])
def display_value(value):
    global k3_global
    k3_global = value
    return 'K3 = ' + str(float(value))


@app.callback(Output('k4-update', 'children'),
              [Input('k4-slider', 'value')])
def display_value(value):
    global k4_global
    k4_global = value
    return 'K4 = ' + str(float(value))


@app.callback(Output('k7-update', 'children'),
              [Input('k7-slider', 'value')])
def display_value(value):
    global k7_global
    k7_global = value
    return 'K7 = ' + str(float(value))


@app.callback(Output('k8-update', 'children'),
              [Input('k8-slider', 'value')])
def display_value(value):
    global k8_global
    k8_global = value
    return 'K8 = ' + str(float(value))


@app.callback(Output('tc-update', 'children'),
              [Input('tc-slider', 'value')])
def display_value(value):
    global tc_global
    tc_global = value
    return 'TC = ' + str(value)


@app.callback(Output('two-sources-graph', 'figure'),
              [Input('button', 'n_clicks')])
def update_output(n_clicks):
    calculate_curves()
    global my_dictionary

    data = [
               go.Scatter(
                   x=my_dictionary['T'],
                   y=my_dictionary['Q'],
                   name='Q',
               ),
               go.Scatter(
                   x=my_dictionary['T'],
                   y=my_dictionary['N'],
                   name='N',
               )
           ]
    fig = {'data': data}
    return fig


def calculate_curves():
    t = 0.0
    jr = 0.0
    dq = 0.0
    dn = 0.0
    global q_global
    global n_global
    global tc_global
    global my_dictionary

    my_q = q_global
    my_n = n_global
    my_t_array = []
    my_q_array = []
    my_n_array = []
    while t < 320:
        jr = j_global / (1.0 + k_global * my_q) * dt_global
        if t < tc_global:
            dq = (k3_global * jr * my_q) - (k8_global * my_q) * dt_global
            my_q = my_q + dq
            dn = 0
        else:
            dq = (k7_global * my_n * my_q) + ((k3_global * jr * my_q) - (
                    k8_global * my_q)) * dt_global
            my_q = my_q + dq
            dn = -(k4_global * my_n * my_q) * dt_global
        my_n = my_n + dn
        t = t + dt_global
        if my_q < 250:
            my_q_array.append(my_q)
            my_t_array.append(t)
            my_n_array.append(my_n)
    my_dictionary["T"] = my_t_array
    my_dictionary["Q"] = my_q_array
    my_dictionary["N"] = my_n_array
    # print(t_dictionary[])
    # print(q_dictionary)
    return 0.0


if __name__ == '__main__':
    app.run_server(debug=True)

Hi @lzanotto,

Please edit you post so that de code apears as a code.

put four ` ``` in a row (no spaces in between) and then your code.
It’s much easier to read and test.

Hi @cecilia,

Thanks for your help, now it looks like a code .

Hi!

What you need to do is replace your callback of the graph (that uses the button) for something like this:

@app.callback(Output('two-sources-graph', 'figure'),
              [Input('dt-slider', 'value'),
               Input('j-slider', 'value'),
               Input('n-slider', 'value'),
               Input('tc-slider', 'value')])

              
def Calculate_curves(dtsli, jsli, nsli, tcsli):
    #ALL Calculation you need to generate your graph based on the input of your sliders.
    #...
    #...
    #...
    figure = ...
    #...
    return figure

in the example I only included 4 of your sliders, you just need to adapt it for more sliders and adapt the function “calculate curves” to use your variables!
The order of the variables is equal of the order of the inputs.
Hope it helped.

Hi @cecilia,

Thank you for your help again. Problem Solved , I figured out the slider id cannot be like ‘dt-slider’, it must be ‘dt_slider’ or something else, using ‘-’ causes problem using it with id as function parameters.

I will close this forum since it is resolved.

There is nothing wrong with using ‘-’ in IDs. Yes, it does not work with function parameters, but the naming of the function parameters is completely arbitrary. You can call them anything you want without changing their value. The first input of your callback will always be used as the first parameter to your function, the second input as the second parameter and so on. Naming does not matter.

1 Like