Cyto Extra Layout not loading in Multipage App

I have app.py:

import dash
import dash_bootstrap_components as dbc

external_stylesheets = [dbc.themes.CERULEAN]
app=dash.Dash(__name__,external_stylesheets=external_stylesheets)

server=app.server

and index.py

from dash import dcc
from dash import html
from dash.dependencies import Input, Output

import dash_bootstrap_components as dbc

# Connect to main app.py file
from app import app
#from app import server
from apps import cyto_compound

app.layout = html.Div(
    [
        dbc.Row(
            #for the moment, we put all in one column
            #but maybe later put in separate columns
            #just put one of each link into a different column
            dbc.Col(
                html.Div(
                    #id='link_list',
                    children=[
                        dcc.Location(id='url',pathname='',refresh=False),
                        dcc.Link('Compounds',href='/apps/cyto_compound'),
                        dcc.Link('Backend Dataset',href='/apps/backend_dataset')
                    ]
                ),

            )
        ),
        dbc.Row(
            dbc.Col(
                html.Div(
                    id='page_content',
                    children=[]
                )
            )
        )
    ]
)

@app.callback(
    [Output(component_id='page_content',component_property='children')],
    [Input(component_id='url',component_property='pathname')]
)
def display_page(temp_pathname):
    if temp_pathname == '/apps/cyto_compound':
        return [cyto_compound.layout]
    else:
        return 'under construction'


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

and one page of my app, cyto_compound.py


import dash_bootstrap_components as dbc
from dash import html
import dash_cytoscape as cyto

import pathlib
import json

from app import app


***cyto.load_extra_layouts()***

PATH = pathlib.Path(__file__).parent
DATA_PATH = PATH.joinpath("../datasets").resolve()



compound_json_address=DATA_PATH.joinpath('cyto_format_compound.json')
temp_json_file=open(compound_json_address,'r')
compound_network_dict=json.load(temp_json_file)
temp_json_file.close()
#the point of this is to add a property that we display.
##we could preprocess this once if we so desired
for temp_element in compound_network_dict['elements']['nodes']:
    #id and label are special keys for cytoscape dicts
    #they are always expected. our conversion script makes the id but does not make the name
    #so we add it manually here
    try:
        temp_element['data']['label']='Bin: '+temp_element['data']['common_name']
    except KeyError:
        temp_element['data']['label']=temp_element['data']['name']



stylesheet=[
    {
        'selector':'node',
        'style':{
            'content':'data(label)',
            'text-wrap':'wrap',
            'text-max-width':100,
            'font-size':13
        }
    },
]





layout=html.Div(
    [
        dbc.Row(
            dbc.Col(
                html.Div(
                    children=[
                        #a header
                        html.H1('Step 1: Choose Compounds')
                    ]
                ),
                width='auto',
            )
        ),
        #justify='center'
        #),
        #compounds
        dbc.Row(
            dbc.Col(
                dbc.Card(
                    children=[
                        #compounds
                        cyto.Cytoscape(
                            id='cytoscape_compound',
                            layout={'name':'cola'},
                            elements=compound_network_dict['elements'],
                            stylesheet=stylesheet,
                            minZoom=0.3,
                            maxZoom=5
                        )
                    ]
                ),
                width='auto',
                align='center'
            )
            #justify='center'
        )
    ]
)

no matter where I put

import dash_cytoscape as cyto
cyto.load_extra_layouts()

I always get

No such layout dagre found. Did you forget to import it and cytoscape.use() it?
The code works when I do not specify a particular layout.

Any ideas?

Did you ever get this to work? I still see this issue, and not sure how to “cytoscape.use()” it.
cytoscape.use() seems to be a JS function and not something you use in Python, obviously, but seems that Cyto module forgot to register the new layouts for use.

at its core - apparently?

I ran an old app and it looked like this

for the life of me, i cant remember what i did, sorry

the conda environment (its a dump) looks like this

name: binvestigate_heroku
channels:

  • conda-forge
  • bioconda
  • defaults
    dependencies:
  • _libgcc_mutex=0.1=conda_forge
  • _openmp_mutex=4.5=2_gnu
  • ansi2html=1.7.0=py38h578d9bd_1
  • anyio=3.6.1=py38h578d9bd_0
  • argon2-cffi=21.3.0=pyhd8ed1ab_0
  • argon2-cffi-bindings=21.2.0=py38h0a891b7_2
  • asttokens=2.0.5=pyhd8ed1ab_0
  • attrs=21.4.0=pyhd8ed1ab_0
  • babel=2.10.1=pyhd8ed1ab_0
  • backcall=0.2.0=pyh9f0ad1d_0
  • backports=1.0=py_2
  • backports.functools_lru_cache=1.6.4=pyhd8ed1ab_0
  • beautifulsoup4=4.11.1=pyha770c72_0
  • biopython=1.79=py38h497a2fe_1
  • bleach=5.0.0=pyhd8ed1ab_0
  • brotli-python=1.0.9=py38hfa26641_7
  • brotlipy=0.7.0=py38h0a891b7_1004
  • bzip2=1.0.8=h7f98852_4
  • c-ares=1.18.1=h7f98852_0
  • ca-certificates=2022.9.24=ha878542_0
  • certifi=2022.9.24=pyhd8ed1ab_0
  • cffi=1.15.0=py38h3931269_0
  • charset-normalizer=2.0.12=pyhd8ed1ab_0
  • colorama=0.4.4=pyh9f0ad1d_0
  • colour=0.1.5=py_0
  • cryptography=37.0.1=py38h9ce1e76_0
  • curl=7.83.1=h2283fc2_0
  • cycler=0.11.0=pyhd8ed1ab_0
  • dash=2.4.1=pyhd8ed1ab_0
  • dash-bio=1.0.1=pyhd8ed1ab_0
  • dash-core-components=2.0.0=pyhd8ed1ab_1
  • dash-html-components=2.0.0=pyhd8ed1ab_1
  • dash-table=5.0.0=pyhd8ed1ab_1
  • debugpy=1.6.0=py38hfa26641_0
  • decorator=5.1.1=pyhd8ed1ab_0
  • defusedxml=0.7.1=pyhd8ed1ab_0
  • entrypoints=0.4=pyhd8ed1ab_0
  • executing=0.8.3=pyhd8ed1ab_0
  • expat=2.4.8=h27087fc_0
  • filprofiler=2022.07.1=py38h0931615_2
  • flit-core=3.7.1=pyhd8ed1ab_0
  • freetype=2.10.4=h0708190_1
  • geoparse=2.0.3=pyhd8ed1ab_0
  • gettext=0.19.8.1=h73d1719_1008
  • git=2.35.3=pl5321h04cb727_0
  • greenlet=1.1.2=py38hfa26641_2
  • icu=67.1=he1b5a44_0
  • idna=3.3=pyhd8ed1ab_0
  • importlib-metadata=4.11.3=py38h578d9bd_1
  • importlib_metadata=4.11.3=hd8ed1ab_1
  • importlib_resources=5.7.1=pyhd8ed1ab_1
  • ipykernel=6.13.0=py38h7f3c49e_0
  • ipython=8.3.0=py38h578d9bd_0
  • ipython_genutils=0.2.0=py_1
  • ipywidgets=7.7.0=pyhd8ed1ab_0
  • jedi=0.18.1=py38h578d9bd_1
  • joblib=1.1.0=pyhd8ed1ab_0
  • json5=0.9.5=pyh9f0ad1d_0
  • jsonschema=4.5.1=pyhd8ed1ab_0
  • jupyter-dash=0.4.2=pyhd8ed1ab_1
  • jupyter_client=7.3.1=pyhd8ed1ab_0
  • jupyter_core=4.10.0=py38h578d9bd_0
  • jupyter_server=1.17.0=pyhd8ed1ab_0
  • jupyterlab=3.4.2=pyhd8ed1ab_0
  • jupyterlab_pygments=0.2.2=pyhd8ed1ab_0
  • jupyterlab_server=2.14.0=pyhd8ed1ab_0
  • jupyterlab_widgets=1.1.0=pyhd8ed1ab_0
  • keyutils=1.6.1=h166bdaf_0
  • kiwisolver=1.4.2=py38h43d8883_1
  • krb5=1.19.3=h08a2579_0
  • ld_impl_linux-64=2.36.1=hea4e1c9_2
  • libblas=3.9.0=14_linux64_openblas
  • libcblas=3.9.0=14_linux64_openblas
  • libcurl=7.83.1=h2283fc2_0
  • libedit=3.1.20191231=he28a2e2_2
  • libev=4.33=h516909a_1
  • libffi=3.4.2=h7f98852_5
  • libgcc-ng=12.1.0=h8d9b700_16
  • libgfortran-ng=12.1.0=h69a702a_16
  • libgfortran5=12.1.0=hdcd56e2_16
  • libgomp=12.1.0=h8d9b700_16
  • libiconv=1.16=h516909a_0
  • liblapack=3.9.0=14_linux64_openblas
  • libnghttp2=1.47.0=he49606f_0
  • libnsl=2.0.0=h7f98852_0
  • libopenblas=0.3.20=pthreads_h78a6416_0
  • libpng=1.6.37=h21135ba_2
  • libpq=13.5=h676c864_1
  • libsodium=1.0.18=h36c2ea0_1
  • libssh2=1.10.0=ha35d2d1_2
  • libstdcxx-ng=12.1.0=ha89aaad_16
  • libuuid=2.32.1=h7f98852_1000
  • libzlib=1.2.11=h166bdaf_1014
  • matplotlib=3.2.2=1
  • matplotlib-base=3.2.2=py38h5d868c9_1
  • matplotlib-inline=0.1.3=pyhd8ed1ab_0
  • mistune=0.8.4=py38h497a2fe_1005
  • nbclassic=0.3.7=pyhd8ed1ab_0
  • nbclient=0.6.3=pyhd8ed1ab_0
  • nbconvert=6.5.0=pyhd8ed1ab_0
  • nbconvert-core=6.5.0=pyhd8ed1ab_0
  • nbconvert-pandoc=6.5.0=pyhd8ed1ab_0
  • nbformat=5.4.0=pyhd8ed1ab_0
  • ncurses=6.3=h27087fc_1
  • nest-asyncio=1.5.5=pyhd8ed1ab_0
  • notebook=6.4.11=pyha770c72_0
  • notebook-shim=0.1.0=pyhd8ed1ab_0
  • openssl=3.0.5=h166bdaf_2
  • packaging=21.3=pyhd8ed1ab_0
  • pandoc=2.18=ha770c72_0
  • pandocfilters=1.5.0=pyhd8ed1ab_0
  • parmed=3.4.3=py38hfa26641_2
  • parso=0.8.3=pyhd8ed1ab_0
  • pcre2=10.37=h032f7d1_0
  • periodictable=1.5.2=py_0
  • perl=5.32.1=2_h7f98852_perl5
  • pexpect=4.8.0=pyh9f0ad1d_2
  • pickleshare=0.7.5=py_1003
  • pip=22.0.4=pyhd8ed1ab_0
  • prometheus_client=0.14.1=pyhd8ed1ab_0
  • prompt-toolkit=3.0.29=pyha770c72_0
  • psutil=5.9.0=py38h0a891b7_1
  • psycopg2=2.9.2=py38h497a2fe_0
  • ptyprocess=0.7.0=pyhd3deb0d_0
  • pure_eval=0.2.2=pyhd8ed1ab_0
  • pycparser=2.21=pyhd8ed1ab_0
  • pygments=2.12.0=pyhd8ed1ab_0
  • pyopenssl=22.0.0=pyhd8ed1ab_0
  • pyparsing=3.0.9=pyhd8ed1ab_0
  • pyrsistent=0.18.1=py38h0a891b7_1
  • pysocks=1.7.1=py38h578d9bd_5
  • python=3.8.13=ha86cf86_0_cpython
  • python-dateutil=2.8.2=pyhd8ed1ab_0
  • python-fastjsonschema=2.15.3=pyhd8ed1ab_0
  • python_abi=3.8=2_cp38
  • pyzmq=23.0.0=py38hfc09fa9_0
  • readline=8.1=h46c0cb4_0
  • requests=2.26.0=pyhd8ed1ab_1
  • retrying=1.3.3=py_2
  • scikit-learn=1.1.1=py38hf80bbf7_0
  • scipy=1.8.0=py38h56a6a73_1
  • send2trash=1.8.0=pyhd8ed1ab_0
  • setuptools=62.3.1=py38h578d9bd_0
  • six=1.16.0=pyh6c4a22f_0
  • sniffio=1.2.0=py38h578d9bd_3
  • soupsieve=2.3.1=pyhd8ed1ab_0
  • sqlalchemy=1.4.27=py38h497a2fe_0
  • sqlite=3.38.5=h4ff8645_0
  • stack_data=0.2.0=pyhd8ed1ab_0
  • tenacity=8.0.1=pyhd8ed1ab_0
  • terminado=0.15.0=py38h578d9bd_0
  • threadpoolctl=3.1.0=pyh8a188c0_0
  • tinycss2=1.1.1=pyhd8ed1ab_0
  • tk=8.6.12=h27826a3_0
  • tornado=6.1=py38h0a891b7_3
  • tqdm=4.64.0=pyhd8ed1ab_0
  • traitlets=5.2.1.post0=pyhd8ed1ab_0
  • typing_extensions=4.2.0=pyha770c72_1
  • urllib3=1.26.9=pyhd8ed1ab_0
  • wcwidth=0.2.5=pyh9f0ad1d_2
  • webencodings=0.5.1=py_1
  • websocket-client=1.3.2=pyhd8ed1ab_0
  • wheel=0.37.1=pyhd8ed1ab_0
  • widgetsnbextension=3.6.0=py38h578d9bd_0
  • xz=5.2.5=h516909a_1
  • zeromq=4.3.4=h9c3ff4c_1
  • zipp=3.8.0=pyhd8ed1ab_0
  • zlib=1.2.11=h166bdaf_1014
  • pip:
    • aniso8601==9.0.1
    • bootstrap-flask==2.0.2
    • click==8.0.1
    • dash-bootstrap-components==0.13.1
    • dash-cytoscape==0.3.0
    • dash-daq==0.5.0
    • flask==2.0.1
    • flask-compress==1.10.1
    • flask-restful==0.3.9
    • gunicorn==20.1.0
    • itsdangerous==2.0.1
    • jinja2==3.0.1
    • markupsafe==2.0.1
    • networkx==2.6.3
    • numpy==1.21.2
    • pandas==1.3.3
    • plotly==5.3.1
    • pytz==2021.1
    • werkzeug==2.0.1
    • wtforms==3.0.1

the layout (also a dump) looks like this

import dash_bootstrap_components as dbc
from dash import html
import dash_cytoscape as cyto
from dash.dependencies import Input, Output, State, ALL, MATCH
from dash.exceptions import PreventUpdate
from dash import callback_context
import dash_core_components as dcc

from itertools import chain
import networkx as nx
import pathlib
import json
from pprint import pprint
import fnmatch

from app import app

cyto.load_extra_layouts()

PATH = pathlib.Path(file).parent
DATA_PATH = PATH.joinpath(“…/datasets”).resolve()

#load the base species network
species_json_address=DATA_PATH.joinpath(‘cyto_format_species.json’)
temp_json_file=open(species_json_address,‘r’)
species_network_dict=json.load(temp_json_file)
temp_json_file.close()
for temp_element in species_network_dict[‘elements’][‘nodes’]:
#id and label are special keys for cytoscape dicts
#they are always expected. our conversion script makes the id but does not make the name
#so we add it manually here
#we do not know how we intend to name species
#try:
temp_element[‘data’][‘label’]=temp_element[‘data’][‘scientific_name’]
#except KeyError:
# temp_element[‘data’][‘label’]=temp_element[‘data’][‘name’]
temp_element[‘classes’]=‘not_selected’

#load the base organ network
organ_json_address=DATA_PATH.joinpath(‘cyto_format_organ.json’)
temp_json_file=open(organ_json_address,‘r’)
organ_network_dict=json.load(temp_json_file)
temp_json_file.close()
for temp_element in organ_network_dict[‘elements’][‘nodes’]:
#id and label are special keys for cytoscape dicts
#they are always expected. our conversion script makes the id but does not make the name
#so we add it manually here
#we do not know how we intend to name organ
#try:
temp_element[‘data’][‘label’]=temp_element[‘data’][‘mesh_label’]
#except KeyError:
# temp_element[‘data’][‘label’]=temp_element[‘data’][‘name’]
temp_element[‘classes’]=‘not_selected’

#load the base disease network
disease_json_address=DATA_PATH.joinpath(‘cyto_format_disease.json’)
temp_json_file=open(disease_json_address,‘r’)
disease_network_dict=json.load(temp_json_file)
temp_json_file.close()
for temp_element in disease_network_dict[‘elements’][‘nodes’]:
#id and label are special keys for cytoscape dicts
#they are always expected. our conversion script makes the id but does not make the name
#so we add it manually here
#we do not know how we intend to name disease
#try:
temp_element[‘data’][‘label’]=temp_element[‘data’][‘mesh_label’]
#except KeyError:
# temp_element[‘data’][‘label’]=temp_element[‘data’][‘name’]
temp_element[‘classes’]=‘not_selected’

#defines the map between the various boxes and the node ids
checklist_hashmap_species={
‘primed apes’: [‘9606’,‘9544’,‘314146’],
‘some plant’:[‘3701’,‘72658’]
}

#defines the map between the various boxes and the node ids
checklist_hashmap_organ={
‘junk’: [‘A01’],
}

#defines the map between the various boxes and the node ids
checklist_hashmap_disease={
‘junk’: [‘C01’],
}

basic_stylesheet=[
{
‘selector’:‘node’,
‘style’:{
‘content’:‘data(label)’,
‘text-wrap’:‘wrap’,
‘text-max-width’:100,
‘font-size’:13
}
},
{
‘selector’:‘.selected’,
‘style’:{
‘background-color’:‘red’
}
},
{
‘selector’:‘.not_selected’,
‘style’:{
‘background-color’:‘grey’
}
}
]

#might want to put this in index?
networkx_address_species=DATA_PATH.joinpath(‘species_networkx.bin’)
networkx_species=nx.readwrite.gpickle.read_gpickle(networkx_address_species)

networkx_address_organ=DATA_PATH.joinpath(‘organ_networkx.bin’)
networkx_organ=nx.readwrite.gpickle.read_gpickle(networkx_address_organ)

networkx_address_disease=DATA_PATH.joinpath(‘disease_networkx.bin’)
networkx_disease=nx.readwrite.gpickle.read_gpickle(networkx_address_disease)

layout=html.Div(
children=[
html.Div(
id=‘div_cytoscape_from_species_cyto’,
children=[
cyto.Cytoscape(
id=‘cytoscape_from_species’,
layout={‘name’:‘dagre’},
elements=species_network_dict[‘elements’],
minZoom=0.3,
maxZoom=5,
stylesheet=basic_stylesheet,
style={‘width’: ‘100%’,‘height’:‘200px’}
)
]
),
html.Div(
children=[
dbc.Row(
dbc.Col(
children=[
dcc.Checklist(
id=‘checklist_from_species’,
options=[
{‘label’: i, ‘value’: i} for i in checklist_hashmap_species.keys()
]
)
],
width=‘auto’,
align=‘center’
)
),
]
),
html.Div(
children=[
dbc.Row(
dbc.Col(
children=[
dcc.Dropdown(
id=‘dropdown_from_species’,
options=[
{‘label’: temp_node[‘data’][‘label’], ‘value’: temp_node[‘data’][‘id’]} for temp_node in species_network_dict[‘elements’][‘nodes’]
],
multi=True
)
],
)
),
]
),
html.Div(
children=[
dbc.Row(
dbc.Col(
children=[
html.Button(
‘Reset selections’,
id=‘button_from_species’,
)
],
)
),
]
),

    html.Div(
        id='div_cytoscape_from_organ_cyto',
        children=[
            cyto.Cytoscape(
                id='cytoscape_from_organ',
                layout={'name':'dagre'},
                elements=organ_network_dict['elements'],
                minZoom=0.3,
                maxZoom=5,
                stylesheet=basic_stylesheet
            )
        ]
    ),
    html.Div(    
        children=[
            dbc.Row(
                dbc.Col(
                    children=[
                        dcc.Checklist(
                            id='checklist_from_organ',
                            options=[
                                {'label': i, 'value': i} for i in checklist_hashmap_organ.keys()
                            ]
                        )
                    ],
                    width='auto',
                    align='center'
                )
            ),
        ]
    ),
    html.Div(    
        children=[
            dbc.Row(
                dbc.Col(
                    children=[
                        dcc.Dropdown(
                            id='dropdown_from_organ',
                            options=[
                                {'label': temp_node['data']['label'], 'value': temp_node['data']['id']} for temp_node in organ_network_dict['elements']['nodes']
                            ],
                            multi=True
                        )
                    ],
                )
            ),
        ]
    ),
    html.Div(    
        children=[
            dbc.Row(
                dbc.Col(
                    children=[
                        html.Button(
                            'Reset selections',
                            id='button_from_organ',
                        )
                    ],
                )
            ),
        ]
    ),

    html.Div(
        id='div_cytoscape_from_disease_cyto',
        children=[
            cyto.Cytoscape(
                id='cytoscape_from_disease',
                layout={'name':'dagre'},
                elements=disease_network_dict['elements'],
                minZoom=0.3,
                maxZoom=5,
                stylesheet=basic_stylesheet
            )
        ]
    ),
    html.Div(    
        children=[
            dbc.Row(
                dbc.Col(
                    children=[
                        dcc.Checklist(
                            id='checklist_from_disease',
                            options=[
                                {'label': i, 'value': i} for i in checklist_hashmap_disease.keys()
                            ]
                        )
                    ],
                    width='auto',
                    align='center'
                )
            ),
        ]
    ),
    html.Div(    
        children=[
            dbc.Row(
                dbc.Col(
                    children=[
                        dcc.Dropdown(
                            id='dropdown_from_disease',
                            options=[
                                {'label': temp_node['data']['label'], 'value': temp_node['data']['id']} for temp_node in disease_network_dict['elements']['nodes']
                            ],
                            multi=True
                        )
                    ],
                )
            ),
        ]
    ),
    html.Div(    
        children=[
            dbc.Row(
                dbc.Col(
                    children=[
                        html.Button(
                            'Reset selections',
                            id='button_from_disease',
                        )
                    ],
                )
            ),
        ]
    ),

]

)

1 Like

Nothing strange looking here, so it must be a bug introduced later…