Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

[solved] Graph created from 2 inputs won't update when changing one of them

Hello everyone,

I’m facing an issue I don’t understand. I did the same thing with random value, it works perfectly fine, but it doesn’t work very well.

The issue is: I have a Dropdown menu and a Radioitem menu from which I want to create a subplot of bar plot. Passing the default values create a perfect subplot, but when I try to change the Radioitem value, the graph from the dropdown value disappear. I use Pycharm and in the debogger, it says the list for table1 is empty.

Here is my code:

import dash
from dash.dependencies import Input, State, Output, Event
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import os
from Bio import SeqIO
from Bio.SeqUtils import ProtParam as pp
from Bio.SeqUtils import seq3
from plotly import tools

app = dash.Dash()

fasta_1a3n = open(os.path.join("data","1a3n.fasta"), "r")
fasta_2gdm = open(os.path.join("data","2gdm.fasta"), "r")
fasta_2qsp = open(os.path.join("data","2qsp.fasta"), "r")
fasta_3hrw = open(os.path.join("data","3hrw.fasta"), "r")
fasta_4odc = open(os.path.join("data","4odc.fasta"), "r")

def choose_fasta(value):
    switcher = {
        "v1a3n": fasta_1a3n,
        "v2gdm": fasta_2gdm,
        "v2qsp": fasta_2qsp,
        "v3hrw": fasta_3hrw,
        "v4odc": fasta_4odc
    }
    return switcher.get(value)

def get_count_aa(value):
    traces = []
    file = choose_fasta(value)
    for entry in SeqIO.parse(file, "fasta"):
        id_prot = entry.id.split("|")
        id_chain = id_prot[0].split(":")
        seq = str(entry.seq)
        X = pp.ProteinAnalysis(seq)
        count_aa = X.count_amino_acids()
        aa_list = []
        aa_count = []
        for key, value in count_aa.items():
            aa_name = seq3(key)
            aa_list.append(aa_name)
            aa_count.append(value)
        traces.append(go.Bar(
            x=aa_list,
            y=aa_count,
            name="Chain " + id_chain[1]
            ))
    return traces


option_species = {"Homo sapiens (Human)": "v1a3n",
                  "Mus musculus (House mouse)":"v3hrw",
                  "Trematomus bernacchii (Emerald rockcod)":"v4odc",
                  "Bos taurus (Cattle)":"v2qsp",
                  "Lupinus luteus (Yellow lupin)":"v2gdm"
                  }

app.layout = html.Div([
    html.Div([
        html.H5(
            "Choose the specie"
        ),
        dcc.Dropdown(
            id="species-name",
            options=[
                {"label": key, "value": value} for key,value in option_species.items()
            ],
            value="v1a3n"
        )
    ],
        style={"padding": "20px"}
    ),
    # html.Div([
        html.Div([
            html.H5(
                "Choose the structure",
            ),
            dcc.Dropdown(
                id="structure-type",
                options=[
                    {"label": "Amino Acids", "value": "AA"},
                    {"label": "Atoms", "value": "atoms"},
                    {"label": "Subunits", "value": "subunits"}
                ],
                value="AA",
            ),
            html.Div([
                dcc.Graph(id="3D-structure")
            ],
            )
        ],
            style={
                "width": "48%",
                "margin-left": "20px",
                "margin-right": "20px",
                "float": "left",
                "display": "inline-block"
            }
        ),
        html.Div([
            html.H5(
                "Composition"
            ),
            dcc.RadioItems(
                id="composition-radio",
                options=[
                    {"label": "Amino acid count", "value": "count"},
                    {"label": "Amino acid percentage", "value": "percentage"},
                    {"label": "Molecular weight", "value": "weight"}
                ],
                value="count",
                labelStyle={"display": "inline-block"}
            ),
            html.Div(
                id="first-species-selected"
            ),
            html.P("Compare with:"),

            dcc.RadioItems(
                id="second-species",
                options=[
                    {"label": "Homo sapiens", "value": "v1a3n"},
                    {"label": "Mus musculus", "value": "v3hrw"},
                    {"label": "Trematomus bernacchii", "value": "v4odc"},
                    {"label": "Bos taurus", "value": "v2qsp"},
                    {"label": "Lupinus luteus", "value": "v2gdm"}
                ],
                value="v3hrw",
                labelStyle={'display': 'inline-block'}
            ),
            dcc.Graph(id="composition-graph")
        ],
            style={
                "padding-right": "20px",
                "padding-left": "20px",
                "float": "left",
                "display": "inline-block"
            }
        ),
])

@app.callback(
    Output("composition-graph", "figure"),
    [Input("composition-radio", "value"),
     Input("species-name", "value"),
     Input("second-species", "value")]
)
def update_comp_graph(comp_entry, drop_entry, radio_entry):
    name1 = [name for name, value in option_species.items() if value == drop_entry]
    name2 = [name for name, value in option_species.items() if value == radio_entry]
    if comp_entry == "count":
        trace1 = get_count_aa(drop_entry)
        trace2 = get_count_aa(radio_entry)
        fig = tools.make_subplots(
            rows=2,
            cols=1,
            shared_xaxes=True,
            subplot_titles=(name1[0], name2[0])
        )
        for trace in trace1:
            fig.append_trace(trace, 1, 1)
        for trace in trace2:
            fig.append_trace(trace, 2, 1)

        fig["layout"].update(
            title="Amino acid count comparison between <br>{} and {}".format(name1[0], name2[0])
        )
        print(fig)
        return fig


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

Please note I didn’t give all my code as it was very long, I just put the callback that causes the issue with the calls for the data.
Thank you for your help!

Hello, that is clear that in callback function, you just plot chart when comp_entry == “count” (

comp_entry == “count”:

So that, when you change the value of radio button, it run into callback, but you don’t handle any thing when

comp_entry == “percentage”: or comp_entry == “weight”:

You should adjust your callback function like that:

if comp_entry == “count”:
# plot chart for count
if comp_entry == “percentage”:
# plot chart for count
if comp_entry == “weight”:
# plot chart for count

Hello, thank you for your answer.
I didn’t write the code for “percentage” and “weight” yet, because my issue isn’t located with the Radioitem “comp_entry” but with the “radio_entry” one. It’s like when I change the value of this one, the “drop_entry” just disappear and gave me a subplot with one graph instead of two. When I play a little bit more with the different values (the drop_entry and radio_entry ones), there is no plot anymore at a certain point.
When I run the pycharm debugger, the “drop_entry” parameter is here when I change the “radio_entry” value, but when it tries to pass it to “table1”, it gives me an empty list, resulting of a subplot with one graph instead of two…

EDIT: I completed the “percentage” and “weight”, but it’s worse, because the subplot just doesn’t appear. It’s like when I try to change the value of one input component, the inputs of the other components just vanish and don’t update the subplot…

OK! I found my error!
I don’t know why I didn’t think about it before, but my data were not stored in a variable, so that’s why they were disappearing…

1 Like