Ejemplo n.º 1
0
 def __init__(self):
     load_extra_layouts()
     super().__init__(id='graph',
                      layout=self.layout(),
                      style={'height': '99vh'},
                      elements=[],
                      stylesheet=self.stylesheet())
Ejemplo n.º 2
0
def get_solution_routing_cytoscape(solution: Solution) -> cyto.Cytoscape:
    """
    Returns a cytoscape object showing the network topology and stream routing
    """

    # elements
    elements = []
    nodes = []
    edges = []

    for n in solution.tc.N.values():
        el = {}
        el["data"] = {"id": n.id, "label": n.id}
        if isinstance(n, end_system):
            el["classes"] = "ES"
        else:
            el["classes"] = "SW"
        nodes.append(el)

    for l in solution.tc.L.values():
        el = {}
        el["data"] = {"source": l.src.id, "target": l.dest.id}
        el["classes"] = "link"
        edges.append(el)

    for f_id, mtree in solution.tc.R.items():
        for l in mtree.get_all_links(solution.tc):
            el = {}
            el["data"] = {"source": l.src.id, "target": l.dest.id}
            el["classes"] = f_id
            edges.append(el)

    elements = flatten([nodes, edges])

    # stylesheet

    stylesheet = flatten(
        [
            _cytoscape_base_stylesheet(),
            _cytoscape_base_stream_selectors(solution.tc.F_routed.keys()),
        ]
    )

    cyto.load_extra_layouts()
    graph = cyto.Cytoscape(
        id="cytoscape-routing-graph",
        layout={"name": "cose"},
        style={"width": "100%", "height": "800px"},
        elements=elements,
        stylesheet=stylesheet,
    )

    return graph
Ejemplo n.º 3
0
def main():
    global parser

    dcy.load_extra_layouts()
    argparser = argparse.ArgumentParser(description='Stormspotter')
    argparser.add_argument("--dbuser", "-dbu", required=True,
                        help='Username for neo4j', default="neo4j")
    argparser.add_argument("--dbpass", "-dbp", required=True,
                        help='Password for neo4j')
    argparser.add_argument("--db",
                        help='Url of database', default="bolt://localhost:7687")

    args = argparser.parse_args()
    # parser = DashParser("neo4j", "password")
    parser = DashParser(args.dbuser, args.dbpass, args.db)
    app.run_server(debug=True, threaded=True)
Ejemplo n.º 4
0
    def __init__(self, graph_one, graph_two, app_display='default'):
        """
        Initialises the dual graph interface and generates the interface layout.

        :param graph_one: (Graph) The first graph for the comparison interface.
        :param graph_two: (Graph) The second graph for the comparison interface.
        :param app_display: (str) 'default' by default and 'jupyter notebook' for running Dash inside Jupyter Notebook.
        """

        # Dash app styling with Bootstrap
        if app_display == 'jupyter notebook':
            self.app = JupyterDash(__name__,
                                   external_stylesheets=[dbc.themes.BOOTSTRAP])
        else:
            self.app = Dash(__name__,
                            external_stylesheets=[dbc.themes.BOOTSTRAP])

        # Setting input graphs as objest variables
        cyto.load_extra_layouts()
        self.graph_one = graph_one
        self.graph_two = graph_two

        # Getting a list of tuples with differnet edge connections
        difference = graph_one.get_difference(graph_two)

        # Updating the elements needed for the Dash Cytoscape Graph object
        self.one_components = None
        self.two_components = None
        self._update_elements_dual(self.graph_one, difference, 1)
        self._update_elements_dual(self.graph_two, difference, 2)

        self.cyto_one = None
        self.cyto_two = None

        # Callback functions to allow simultaneous node selection when clicked
        self.app.callback(Output('cytoscape_two',
                                 'elements'), [Input('cytoscape', 'tapNode')],
                          [State('cytoscape_two', 'elements')])(
                              DualDashGraph._select_other_graph_node)
        self.app.callback(Output('cytoscape', 'elements'),
                          [Input('cytoscape_two', 'tapNode')],
                          [State('cytoscape', 'elements')])(
                              DualDashGraph._select_other_graph_node)
def get_layout():
    cyto.load_extra_layouts()

    return html.Div([
        cyto.Cytoscape(
            id='cytoscape',
            layout={
                'name': 'dagre',
                'nodeDimensionsIncludeLabels': True,
                'animate': True,
            },
            elements=[],
            style={'width': 'auto', 'height': '100vh'},
        ),

        #class and feature names
        html.Div(id='names', style={'display': 'none'}),
        #decision tree
        html.Div(id='tree', style={'display': 'none'}),
        #visible nodes
        html.Div(id='visible', style={'display': 'none'}),
        #collapsed leaves
        html.Div(id='collapsed_leaf', style={'display': 'none'}),
    ])
Ejemplo n.º 6
0
			'opacity': 1,
			'label': label,
			'background-color': negative_color,
		}
	},
	{
		'selector': 'edge',						# for the edges
		'style': {
			'line-color': '#C5D3E2',			# very ligth blue
			'curve-style': 'haystack'
		}
	}
]

# Necessary to get more cytoscape layouts
cyto.load_extra_layouts()

"""
#####################
##  Middle window  ##
#####################
"""

# This will appear above the cytoscape node graph
node_graph_layout = dbc.Row(
	[
		dbc.Col(
			[
				# Drop down selector for layout of cytoscape, at the top of the page
				html.Main("Choose graph layout style:"),
				dcc.Dropdown(
Ejemplo n.º 7
0
from propnet.web.layouts_home import home_layout
from propnet.web.layouts_interactive import interactive_layout
from propnet.web.layouts_correlate import correlate_layout
from propnet.web.layouts_explore import explore_layout
from propnet.web.layout_refs import refs_layout

from dash_cytoscape import load_extra_layouts

from propnet.web.utils import parse_path

from flask_caching import Cache
import logging

log = logging.getLogger(__name__)

load_extra_layouts()

# TODO: Fix math rendering

app = dash.Dash(__name__)
server = app.server
app.config.suppress_callback_exceptions = True  # TODO: remove this?
app.scripts.config.serve_locally = True
app.title = "propnet"
route = dcc.Location(id='url', refresh=False)

cache = Cache(app.server,
              config={
                  'CACHE_TYPE': 'filesystem',
                  'CACHE_DIR': '.tmp'
              })
def prep_dash(elements):
    cyto.load_extra_layouts()
    app = dash.Dash(external_stylesheets=[dbc.themes.LUX])
    app.layout = html.Div([
        dbc.Row([
            dbc.Col(
                [
                    cyto.Cytoscape(
                        id='org-chart',
                        layout={
                            'name': 'klay'
                        },  # circle, dagre & klay work fast, cose & spread work slow
                        style={
                            'width': '100%',
                            'height': '95vh'
                        },
                        elements=elements,
                        # minZoom = 0.02, maxZoom = 2,
                        stylesheet=[{
                            'selector': 'node',
                            'style': {
                                'label': 'data(label)',
                                'height': 'data(soc_size)',
                                'width': 'data(soc_size)'
                            }
                        }, {
                            "selector": 'edge',
                            'style': {
                                "curve-style": "unbundled-bezier",
                                "opacity": 1,
                                'width': 1
                            }
                        }, {
                            'selector': '.city_1',
                            'style': {
                                'background-color': '#00DCA8'
                            }
                        }, {
                            'selector': '.city_2',
                            'style': {
                                'background-color': '#DABC3B'
                            }
                        }, {
                            'selector': '.city_3',
                            'style': {
                                'background-color': '#179BFF'
                            }
                        }, {
                            'selector': '.city_oth',
                            'style': {
                                'background-color': '#FF4D53'
                            }
                        }, {
                            'selector': '.city_unk',
                            'style': {
                                'background-color': '#AAAAAA'
                            }
                        }, {
                            'selector': '.square',
                            'style': {
                                'shape': 'square'
                            }
                        }, {
                            'selector': '.circle',
                            'style': {
                                'shape': 'circle'
                            }
                        }, {
                            'selector': '.diamond',
                            'style': {
                                'shape': 'diamond'
                            }
                        }, {
                            'selector': '.triangle',
                            'style': {
                                'shape': 'triangle'
                            }
                        }, {
                            'selector': '.border_1',
                            'style': {
                                'border-width': 2,
                                'border-color': '#111111'
                            }
                        }, {
                            'selector': '.border_0',
                            'style': {
                                'border-width': 1,
                                'border-color': '#FF0000'
                            }
                        }, {
                            'selector': '.link_1',
                            'style': {
                                'line-color': '#941100'
                            }
                        }, {
                            'selector': '.link_2',
                            'style': {
                                'line-color': '#929000'
                            }
                        }, {
                            'selector': '.link_3',
                            'style': {
                                'line-color': '#008F00'
                            }
                        }, {
                            'selector': '.link_4',
                            'style': {
                                'line-color': '#0096FF'
                            }
                        }, {
                            'selector': '.link_5',
                            'style': {
                                'line-color': '#FF9300'
                            }
                        }, {
                            'selector': '.link_6',
                            'style': {
                                'line-color': '#00FA92'
                            }
                        }, {
                            'selector': '.link_7',
                            'style': {
                                'line-color': '#FF85FF'
                            }
                        }, {
                            'selector': '.link_8',
                            'style': {
                                'line-color': '#9437FF'
                            }
                        }, {
                            'selector': '.link_0',
                            'style': {
                                'line-color': '#A9A9A9'
                            }
                        }, {
                            'selector': '.parent_1',
                            'style': {
                                'background-color': '#FFD0CB'
                            }
                        }, {
                            'selector': '.parent_2',
                            'style': {
                                'background-color': '#FFFD99'
                            }
                        }, {
                            'selector': '.parent_3',
                            'style': {
                                'background-color': '#CCFFCC'
                            }
                        }, {
                            'selector': '.parent_4',
                            'style': {
                                'background-color': '#99D6FF'
                            }
                        }, {
                            'selector': '.parent_5',
                            'style': {
                                'background-color': '#FFE2BD'
                            }
                        }, {
                            'selector': '.parent_6',
                            'style': {
                                'background-color': '#BCFFE3'
                            }
                        }, {
                            'selector': '.parent_7',
                            'style': {
                                'background-color': '#FFCCFF'
                            }
                        }, {
                            'selector': '.parent_8',
                            'style': {
                                'background-color': '#E3CCFF'
                            }
                        }, {
                            'selector': '.parent_0',
                            'style': {
                                'background-color': '#EEEEEE'
                            }
                        }])
                ],
                width=12)
        ])
    ])

    return app
Ejemplo n.º 9
0
def graph(G, mode="external", **kwargs):
    """
    G: a multidirectional graph

    kwargs are passed to the Jupyter_Dash.run_server() function. Some usefull arguments are:
        mode: "inline" to run app inside the jupyter nodebook, default is external 
        debug: True or False, Usefull to catch errors during development.
    """

    import dash
    from jupyter_dash import JupyterDash
    import dash_cytoscape as cyto
    from dash.dependencies import Output, Input
    import dash_html_components as html
    import dash_core_components as dcc
    import dash_table
    import networkx as nx
    import scConnect as cn
    import plotly.graph_objs as go
    import plotly.io as pio
    import pandas as pd
    import numpy as np
    import json
    import matplotlib
    import matplotlib.pyplot as plt
    pio.templates.default = "plotly_white"

    cyto.load_extra_layouts()

    JupyterDash.infer_jupyter_proxy_config()

    app = JupyterDash(__name__)

    server = app.server
    # Add a modified index string to change the title to scConnect
    app.index_string = '''
        <!DOCTYPE html>
        <html>
            <head>
                {%metas%}
                <title>scConnect</title>
                {%favicon%}
                {%css%}
            </head>
            <body>
                {%app_entry%}
                <footer>
                    {%config%}
                    {%scripts%}
                    {%renderer%}
            </body>
        </html>
        '''
    # Add colors to each node
    nodes = pd.Categorical(G.nodes())
    # make a list of RGBA tuples, one for each node
    colors = plt.cm.tab20c(nodes.codes / len(nodes.codes), bytes=True)
    # zip node to color
    color_map_nodes = dict(zip(nodes, colors))

    # add these colors to original graph
    for node, color in color_map_nodes.items():
        G.nodes[node]["color"] = color[0:3]  # Save only RGB

    # Add colors to edges(source node color) for  G
    for u, v, k in G.edges(keys=True):
        G.edges[u, v, k]["color"] = color_map_nodes[u][0:3]

    # load graph into used formes
    def G_to_flat(G, weight):
        G_flat = cn.graph.flatten_graph(G, weight=weight, log=True)

        # Add colors to edges(source node color) for G_flat
        for u, v, in G_flat.edges():
            G_flat.edges[u, v]["color"] = color_map_nodes[u][0:3]
        return G_flat

    # produce full graph variante to extract metadata
    G_flat = G_to_flat(G, weight="score")
    G_split = cn.graph.split_graph(G)

    # find and sort all found interactions
    interactions = list(G_split.keys())
    interactions.sort()

    G_cyto = nx.cytoscape_data(G_flat)

    # get min and max weight for all edges for flat and normal graph
    #weights = [d["weight"] for u, v, d in G_flat.edges(data=True)]
    scores = [d["score"] for u, v, d in G.edges(data=True)]
    cent = [d["centrality"] for n, d in G.nodes(data=True)]

    # prepare data for network graph
    nodes = G_cyto["elements"]["nodes"]
    elements = []

    # collect all available genes
    genes = list(nodes[0]["data"]["genes"].keys())

    # Styling parameters
    font_size = 20

    # Style for network graph
    default_stylesheet = [{
        'selector': 'node',
        'style': {
            'background-color': 'data(color)',
            'label': 'data(id)',
            'shape': 'ellipse',
            'opacity': 1,
            'font-size': f'{font_size}',
            'font-weight': 'bold',
            'text-wrap': 'wrap',
            'text-max-width': "100px",
            'text-opacity': 1,
            'text-outline-color': "white",
            'text-outline-opacity': 1,
            'text-outline-width': 2
        }
    }, {
        'selector': 'node:selected',
        'style': {
            'background-color': 'data(color)',
            'label': 'data(id)',
            'shape': 'ellipse',
            'opacity': 1,
            'border-color': "black",
            'border-width': "5"
        }
    }, {
        'selector': 'edge',
        'style': {
            'line-color': 'data(color)',
            "opacity": 0.7,
            "curve-style": "unbundled-bezier",
            "width": "data(weight)",
            "target-arrow-shape": "vee",
            "target-arrow-color": "black",
            'z-index': 1,
            'font-size': f'{font_size}'
        }
    }, {
        'selector': 'edge:selected',
        'style': {
            'line-color': 'red',
            'line-style': "dashed",
            'opacity': 1,
            'z-index': 10,
        }
    }]
    app.layout = html.Div(
        className="wrapper",
        children=[  # wrapper
            html.Div(
                className="header",
                children=[  # header
                    html.Img(src="assets/logo.png", alt="scConnect logo"),
                    html.Div(
                        className="graph-info",
                        id="graph-stat",
                        children=[
                            html.
                            H3(f'Loaded graph with {len(G.nodes())} nodes and {len(G.edges())} edges'
                               )
                        ])
                ]),
            html.Div(
                className="network-settings",
                children=[  # network settings
                    html.H2("Network settings", style={"text-align":
                                                       "center"}),
                    html.Label("Interactions"),
                    dcc.Dropdown(id="network-interaction",
                                 options=[{
                                     'label': "all interactions",
                                     'value': "all"
                                 }] + [{
                                     'label': interaction,
                                     'value': interaction
                                 } for interaction in interactions],
                                 value="all"),
                    # select if only significant ligands and receptors should be shown
                    html.Label("Graph weight:"),
                    dcc.RadioItems(id="weight-select",
                                   options=[{
                                       "label": "Score",
                                       "value": "score"
                                   }, {
                                       "label": "Log score",
                                       "value": "log_score"
                                   }, {
                                       "label": "Specificity",
                                       "value": "specificity"
                                   }, {
                                       "label": "Importance",
                                       "value": "importance"
                                   }],
                                   value="importance",
                                   labelStyle={
                                       'display': 'block',
                                       "margin-left": "50px"
                                   },
                                   style={
                                       "padding": "10px",
                                       "margin": "auto"
                                   }),
                    html.Label("Graph Layout"),
                    dcc.Dropdown(
                        id="network-layout",
                        options=[{
                            'label':
                            name.capitalize(),
                            'value':
                            name
                        } for name in [
                            'grid', 'random', 'circle', 'cose', 'concentric',
                            'breadthfirst', 'cose-bilkent', 'cola', 'euler',
                            'spread', 'dagre', 'klay'
                        ]],
                        value="circle",
                        clearable=False),
                    html.Label("Weight Filter",
                               style={
                                   "paddingBottom": 500,
                                   "paddingTop": 500
                               }),
                    dcc.
                    Slider(  # min, max and value are set dynamically via a callback
                        id="network-filter",
                        step=0.001,
                        updatemode="drag",
                        tooltip={
                            "always_visible": True,
                            "placement": "right"
                        },
                    ),
                    html.Label("Node size"),
                    dcc.RangeSlider(id="node-size",
                                    value=[10, 50],
                                    min=0,
                                    max=100,
                                    updatemode="drag"),
                    html.Label("Select gene"),
                    dcc.Dropdown(
                        id="gene_dropdown",
                        options=[{
                            "label": gene,
                            "value": gene
                        } for gene in genes],
                        clearable=True,
                        placeholder="Color by gene expression",
                    ),

                    # Store node colors "hidden" for gene expresison
                    html.Div(id="node-colors",
                             style={"display": "none"},
                             children=[""]),
                    html.Div(id="min-max", children=[]),
                    # Click to download image of network graph
                    html.Button(children="Download current view",
                                id="download-network-graph",
                                style={"margin": "10px"})
                ]),  # end network settings
            html.Div(
                id="network-graph",
                className="network-graph",
                children=[  # network graph
                    html.H2("Network graph", style={"text-align": "center"}),
                    cyto.Cytoscape(id="cyto-graph",
                                   style={
                                       'width': '100%',
                                       'height': '80vh'
                                   },
                                   stylesheet=default_stylesheet,
                                   elements=elements,
                                   autoRefreshLayout=True,
                                   zoomingEnabled=False)
                ]),  # end network graph
            html.Div(
                className="sankey-settings",
                children=[  # network settings
                    html.H2("Sankey Settings", style={"text-align": "center"}),
                    html.Label("Weight Filter"),
                    dcc.Slider(id="sankey-filter",
                               min=min(scores),
                               max=max(scores),
                               value=0.75,
                               step=0.001,
                               updatemode="drag",
                               tooltip={
                                   "always_visible": True,
                                   "placement": "right"
                               }),
                    html.Label("Toggle weighted"),
                    dcc.RadioItems(id="sankey-toggle",
                                   options=[{
                                       "label": "Score",
                                       "value": "score"
                                   }, {
                                       "label": "Log score",
                                       "value": "log_score"
                                   }, {
                                       "label": "Specificity",
                                       "value": "specificity"
                                   }, {
                                       "label": "Importance",
                                       "value": "importance"
                                   }],
                                   value="importance",
                                   labelStyle={"display": "block"})
                ]),  # end network settings
            html.Div(
                className="sankey",
                id="sankey",
                children=[  # sankey graph
                    html.H2("Sankey graph", style={"text-align": "center"}),
                    dcc.Graph(id="sankey-graph")
                ]),  # end sankey graph
            html.Div(
                className="interaction-list",
                children=[  # interaction list
                    html.Div(id="selection",
                             children=[
                                 html.H2("Interactions",
                                         style={"text-align": "center"}),
                                 html.H3(id="edge-info",
                                         style={"text-align": "center"}),
                                 dcc.Graph(id="interaction-scatter"),
                                 html.Div(id="interaction-selection",
                                          style={"display": "none"},
                                          children=[""])
                             ]),
                    html.Div(children=[
                        dash_table.DataTable(
                            id="edge-selection",
                            page_size=20,
                            style_table={
                                "overflowX": "scroll",
                                "overflowY": "scroll",
                                "height": "50vh",
                                "width": "95%"
                            },
                            style_cell_conditional=[{
                                "if": {
                                    "column_id": "interaction"
                                },
                                "textAlign": "left"
                            }, {
                                "if": {
                                    "column_id": "receptorfamily"
                                },
                                "textAlign": "left"
                            }, {
                                "if": {
                                    "column_id": "pubmedid"
                                },
                                "textAlign": "left"
                            }],
                            style_header={
                                "fontWeight": "bold",
                                "maxWidth": "200px",
                                "minWidth": "70px"
                            },
                            style_data={
                                "maxWidth": "200px",
                                "minWidth": "70px",
                                "textOverflow": "ellipsis"
                            },
                            sort_action="native",
                            fixed_rows={
                                'headers': True,
                                'data': 0
                            })
                    ])
                ]),  # end interaction list
            html.Div(
                className="L-R-scores",
                children=[  # ligand and receptor lists
                    html.H2("Ligand and receptors",
                            style={"text-align": "center"}),
                    html.Div(children=[
                        html.H3(
                            id="selected-node",
                            style={"text-align": "center"},
                            children=["Select a node in the notwork graph"]),
                        html.Label("Search for ligands and receptors:",
                                   style={"margin-right": "10px"}),
                        dcc.Input(id="filter_l_r",
                                  type="search",
                                  value="",
                                  placeholder="Search")
                    ]),
                    dcc.Tabs([
                        dcc.Tab(label="Ligands",
                                children=[
                                    dcc.Graph(id="ligand-graph",
                                              config=dict(autosizable=True,
                                                          responsive=True)),
                                    dash_table.DataTable(
                                        id="ligand-table",
                                        page_size=20,
                                        style_table={
                                            "overflowX": "scroll",
                                            "overflowY": "scroll",
                                            "height": "50vh",
                                            "width": "95%"
                                        },
                                        style_cell_conditional=[{
                                            "if": {
                                                "column_id": "Ligand"
                                            },
                                            "textAlign":
                                            "left"
                                        }],
                                        style_header={
                                            "fontWeight": "bold",
                                            "maxWidth": "200px",
                                            "minWidth": "70px"
                                        },
                                        style_data={
                                            "maxWidth": "200px",
                                            "minWidth": "70px",
                                            "textOverflow": "ellipsis"
                                        },
                                        sort_action="native",
                                        fixed_rows={
                                            'headers': True,
                                            'data': 0
                                        })
                                ]),
                        dcc.Tab(label="Receptors",
                                children=[
                                    dcc.Graph(id="receptor-graph",
                                              config=dict(autosizable=True,
                                                          responsive=True)),
                                    dash_table.DataTable(
                                        id="receptor-table",
                                        page_size=20,
                                        style_table={
                                            "overflowX": "scroll",
                                            "overflowY": "scroll",
                                            "height": "50vh",
                                            "width": "95%"
                                        },
                                        style_cell_conditional=[{
                                            "if": {
                                                "column_id": "Receptor"
                                            },
                                            "textAlign":
                                            "left"
                                        }],
                                        style_header={
                                            "fontWeight": "bold",
                                            "maxWidth": "200px",
                                            "minWidth": "70px"
                                        },
                                        style_data={
                                            "maxWidth": "200px",
                                            "minWidth": "70px",
                                            "textOverflow": "ellipsis"
                                        },
                                        sort_action="native",
                                        fixed_rows={
                                            'headers': True,
                                            'data': 0
                                        })
                                ])
                    ])
                ])  # end ligand receptor list
        ])  # end wrapper

    # Instantiate the graph and produce the bounderies for filters
    @app.callback([
        Output("cyto-graph", "elements"),
        Output("network-filter", "min"),
        Output("network-filter", "max"),
        Output("network-filter", "value")
    ], [
        Input("network-interaction", "value"),
        Input("weight-select", "value")
    ])
    def make_graph(interaction, score):
        G_flat = G_to_flat(G, score)

        if interaction == "all":  # if no interaction is selected, use full graph
            G_cyto = nx.cytoscape_data(G_flat)
            weights = [d["weight"] for u, v, d in G_flat.edges(data=True)]

            # prepare data for network graph
            nodes = G_cyto["elements"]["nodes"]
            edges = G_cyto["elements"]["edges"]
            elements = nodes + edges

            return elements, min(weights), max(weights), np.mean(weights)

        else:  # an interaction is selected, select only that interaction
            G_split = cn.graph.split_graph(G)
            G_split_flat = G_to_flat(G_split[interaction], score)
            G_cyto = nx.cytoscape_data(G_split_flat)
            weights = [
                d["weight"] for u, v, d in G_split_flat.edges(data=True)
            ]

            # prepare data for network graph
            nodes = G_cyto["elements"]["nodes"]
            edges = G_cyto["elements"]["edges"]
            elements = nodes + edges

            return elements, min(weights), max(weights), np.mean(weights)

    # Change layout of network graph

    @app.callback(Output("cyto-graph", "layout"),
                  [Input("network-layout", "value")])
    def update_network_layout(layout):
        return {"name": layout, "automate": True, "fit": True}

    # Choose gene to color nodes by

    @app.callback(
        [Output("node-colors", "children"),
         Output("min-max", "children")], [Input("gene_dropdown", "value")])
    def calculate_colors(gene):
        if gene is None:
            return [None, ""]
        # get all gene expression values for selected gene
        gene_data = {
            celltype["data"]["id"]: celltype["data"]["genes"][gene]
            for celltype in nodes
        }

        min_value = min(gene_data.values())
        max_value = max(gene_data.values())

        # package min max expression information to a list that will be returned
        expression = html.Ul(children=[
            html.Li(f"minimum gene expression: {min_value}"),
            html.Li(f"maximum gene expression: {max_value}")
        ])

        cmap = matplotlib.cm.get_cmap("coolwarm")

        color_dict = dict()
        for k, v in gene_data.items():
            color_dict[k] = {"rgb": cmap(v, bytes=True)[0:3], "expression": v}

        color = pd.Series(color_dict)

        return color.to_json(), expression

    # Select visible edges of network graph depending on filter value
    # node color depending on selected gene
    # width of edges

    @app.callback(Output("cyto-graph", "stylesheet"), [
        Input("network-filter", "value"),
        Input("network-filter", "min"),
        Input("network-filter", "max"),
        Input("node-size", "value"),
        Input("node-colors", "children")
    ])
    def style_network_graph(th, min_weight, max_weight, size, colors):

        # create a filter for edges
        filter_style = [{
            "selector": f"edge[weight < {th}]",
            "style": {
                "display": "none"
            }
        }, {
            "selector": "node",
            "style": {
                'height':
                f'mapData(centrality, {min(cent)}, {max(cent)}, {size[0]}, {size[1]})',
                'width':
                f'mapData(centrality, {min(cent)}, {max(cent)}, {size[0]}, {size[1]})'
            }
        }]

        # create a color style for nodes based on gene expression
        if isinstance(colors, str):
            colors = pd.read_json(colors, typ="series", convert_dates=False)
            color_style = [{
                'selector': f'node[id = "{str(index)}"]',
                'style': {
                    'background-color': f'rgb{tuple(colors[index]["rgb"])}'
                }
            } for index in colors.index]
            filter_style += color_style
        else:
            color_style = {
                "selector": "node",
                "style": {
                    'background-color': 'BFD7B5'
                }
            }

        # Map edges width to a set min and max value (scale for visibility)
        edge_style = [{
            "selector": "edge",
            "style": {
                "width": f"mapData(weight, {min_weight}, {max_weight}, 1, 10)"
            }
        }]

        return default_stylesheet + filter_style + edge_style

    # download an image of current network graph view
    @app.callback(Output("cyto-graph", "generateImage"),
                  Input("download-network-graph", "n_clicks"))
    def download_networkgraph_image(get_request):

        if get_request == None:
            return dict()

        return {"type": "svg", "action": "download"}

    # Produce a table of all edge data from tapped edge
    @app.callback([
        Output("edge-info", "children"),
        Output("edge-selection", "columns"),
        Output("edge-selection", "data")
    ], [
        Input("cyto-graph", "tapEdgeData"),
        Input("interaction-selection", "children")
    ])
    def update_data(edge, selection):
        import pandas as pd
        import json

        # check if an edge has really been clicked, return default otherwise
        if edge is None:
            return ["", None, None]

        info = f"Interactions from {edge['source']} to {edge['target']}."

        # map visible names for columns with columns in edge[interaction]
        columns = [{
            "name": "Interaction",
            "id": "interaction"
        }, {
            "name": "Receptor Family",
            "id": "receptorfamily"
        }, {
            "name": "Score",
            "id": "score"
        }, {
            "name": "Log10(score)",
            "id": "log_score"
        }, {
            "name": "Specificity",
            "id": "specificity"
        }, {
            "name": "Importance",
            "id": "importance"
        }, {
            "name": "Ligand z-score",
            "id": "ligand_zscore"
        }, {
            "name": "Ligand p-value",
            "id": "ligand_pval"
        }, {
            "name": "Receptor z-score",
            "id": "receptor_zscore"
        }, {
            "name": "Receptor p-value",
            "id": "receptor_pval"
        }, {
            "name": "PubMed ID",
            "id": "pubmedid"
        }]

        interactions = pd.DataFrame(edge["interactions"])[[
            "interaction", "receptorfamily", "score", "log_score",
            "specificity", "importance", "ligand_zscore", "ligand_pval",
            "receptor_zscore", "receptor_pval", "pubmedid"
        ]]

        # Sort values based on score
        interactions.sort_values(by="score", ascending=False, inplace=True)

        # round values for scores to two decimals
        interactions[[
            "score", "log_score", "specificity", "importance", "ligand_zscore",
            "receptor_zscore"
        ]] = interactions[[
            "score", "log_score", "specificity", "importance", "ligand_zscore",
            "receptor_zscore"
        ]].round(decimals=2)

        interactions[["ligand_pval", "receptor_pval"
                      ]] = interactions[["ligand_pval",
                                         "receptor_pval"]].round(decimals=4)

        # if selection from interaction graph, filter dataframe
        if selection != "":
            selection = json.loads(selection)
            interactions = interactions.loc[interactions["interaction"].isin(
                selection)]

        records = interactions.to_dict("records")

        return [info, columns, records]

    @app.callback([Output("interaction-scatter", "figure")],
                  [Input("cyto-graph", "tapEdgeData")])
    def interaction_scatter_plot(edge):
        import plotly.express as px

        fig = go.Figure()
        if not isinstance(edge, dict):
            return [
                fig,
            ]

        interactions = pd.DataFrame(edge["interactions"])[[
            "interaction", "receptorfamily", "score", "log_score",
            "ligand_zscore", "ligand_pval", "receptor_zscore", "receptor_pval",
            "specificity", "importance", "pubmedid"
        ]]

        # add 10% to the min and max value to not clip the datapoint
        range_x = (-max(interactions["log_score"]) * 0.1,
                   max(interactions["log_score"]) * 1.1)
        range_y = (-max(interactions["specificity"]) * 0.1,
                   max(interactions["specificity"]) * 1.1)
        #interactions["specificity"] = np.log10( interactions["specificity"])

        fig = px.scatter(interactions,
                         x="log_score",
                         range_x=range_x,
                         y="specificity",
                         range_y=range_y,
                         color="importance",
                         hover_name="interaction",
                         hover_data=[
                             "ligand_pval", "receptor_pval", "score",
                             "specificity", "receptorfamily"
                         ],
                         color_continuous_scale=px.colors.sequential.Viridis_r,
                         labels={
                             "ligand_zscore": "Ligand Z-score",
                             "receptor_zscore": "Receptor Z-score",
                             "log_score": "log(Interaction score)",
                             "score": "Interaction score",
                             "specificity": "Specificity",
                             "importance": "Importance",
                             "receptorfamily": "Receptor family",
                             "pubmedid": "PubMed ID",
                             "ligand_pval": "Ligand p-value",
                             "receptor_pval": "Receptor p-value"
                         })
        return [
            fig,
        ]

    @app.callback(Output("interaction-selection", "children"),
                  [Input("interaction-scatter", "selectedData")])
    def interaction_select(selected_data):
        import json
        if isinstance(selected_data, dict):
            interactions = [
                point["hovertext"] for point in selected_data["points"]
            ]
        else:
            return ""
        return json.dumps(interactions)

    # Produce ligand and receptor graphs based on tapped node

    @app.callback([
        Output("ligand-graph", "figure"),
        Output("receptor-graph", "figure"),
        Output("selected-node", "children")
    ], [Input("cyto-graph", "tapNodeData"),
        Input("filter_l_r", "value")])
    def plot_l_r_expression(node, filter_text):

        # set output variables to empty figures
        ligand_fig = go.Figure()
        receptor_fig = go.Figure()
        node_id = "Select a node in the network graph"

        if isinstance(node, dict):
            import plotly.express as px

            node_id = node["id"]

            ligands_score = pd.DataFrame.from_dict(node["ligands_score"],
                                                   orient="index",
                                                   columns=["Score"])
            ligands_zscore = np.log2(
                pd.DataFrame.from_dict(node["ligands_zscore"],
                                       orient="index",
                                       columns=["Z-score"]))
            ligands_corr_pval = pd.DataFrame.from_dict(
                node["ligands_corr_pval"], orient="index", columns=["p-value"])
            ligands_merge = ligands_score.merge(ligands_zscore,
                                                how="left",
                                                left_index=True,
                                                right_index=True)
            ligands_merge = ligands_merge.merge(ligands_corr_pval,
                                                how="left",
                                                left_index=True,
                                                right_index=True)
            ligands_merge["log(score + 1)"] = np.log10(ligands_merge["Score"] +
                                                       1)
            ligands_merge["Significant"] = [
                True if p_val < 0.05 else False
                for p_val in ligands_merge["p-value"]
            ]
            ligands_merge["-log(p-value)"] = -np.log10(
                ligands_merge["p-value"])

            if filter_text != "":
                ligands_merge = ligands_merge.filter(like=filter_text, axis=0)

            ligand_fig = px.scatter(ligands_merge,
                                    x="log(score + 1)",
                                    y="-log(p-value)",
                                    color="Significant",
                                    hover_name=ligands_merge.index,
                                    hover_data=["Score", "Z-score", "p-value"])

            receptors_score = pd.DataFrame.from_dict(node["receptors_score"],
                                                     orient="index",
                                                     columns=["Score"])
            receptors_zscore = np.log2(
                pd.DataFrame.from_dict(node["receptors_zscore"],
                                       orient="index",
                                       columns=["Z-score"]))
            receptors_corr_pval = pd.DataFrame.from_dict(
                node["receptors_corr_pval"],
                orient="index",
                columns=["p-value"])
            receptors_merge = receptors_score.merge(receptors_zscore,
                                                    how="left",
                                                    left_index=True,
                                                    right_index=True)
            receptors_merge = receptors_merge.merge(receptors_corr_pval,
                                                    how="left",
                                                    left_index=True,
                                                    right_index=True)
            receptors_merge["log(score + 1)"] = np.log10(
                receptors_merge["Score"] + 1)
            receptors_merge["Significant"] = [
                True if p_val < 0.05 else False
                for p_val in receptors_merge["p-value"]
            ]
            receptors_merge["-log(p-value)"] = -np.log10(
                receptors_merge["p-value"])

            if filter_text != "":
                receptors_merge = receptors_merge.filter(like=filter_text,
                                                         axis=0)

            receptor_fig = px.scatter(
                receptors_merge,
                x="log(score + 1)",
                y="-log(p-value)",
                color="Significant",
                hover_name=receptors_merge.index,
                hover_data=["Score", "Z-score", "p-value"])

        return [ligand_fig, receptor_fig, node_id]

    # Builds a sankey graph based on the tapped node (store in global G_s)
    G_s = nx.MultiDiGraph()  #variable holding sankey graph

    @app.callback([
        Output("sankey-filter", "min"),
        Output("sankey-filter", "max"),
        Output("sankey-filter", "value")
    ], [Input("cyto-graph", "tapNodeData"),
        Input("sankey-toggle", "value")])
    def build_sankey_graph(node, score):
        import numpy as np
        # If no node has been selected, dont try to build graph
        if node is None:
            return (0, 0, 0)

        node = node["id"]
        # Find all interactions where node is target or source node
        nonlocal G_s
        G_s = nx.MultiDiGraph()  # reset content
        weight = list(
        )  # list to store all weights (used to set min and max for the filter)
        for n, nbrs in G.adj.items(
        ):  # graph has been modified by network graph before
            for nbr, edict in nbrs.items():
                if n == node:
                    for e, d in edict.items():
                        G_s.add_edge(n, " Post " + nbr, **d)
                        weight.append(d[score])
                if nbr == node:
                    for e, d in edict.items():
                        G_s.add_edge("Pre " + n, nbr, **d)
                        weight.append(d[score])

        if len(weight) == 0:
            weight = [0, 1]
        if score == "specificity":
            # set default start value to specificity value for ligand and receptor
            # p-value of (0.05 and 0.05)/2 = 1.3
            return (min(weight), max(weight), 1.3)
        return (min(weight), max(weight), np.mean(weight))

    @app.callback(Output("sankey-graph", "figure"), [
        Input("sankey-filter", "value"),
        Input("sankey-toggle", "value"),
        Input("cyto-graph", "tapNodeData")
    ])
    def filter_sankey_graph(th, score, node):

        if node:
            node = node["id"]

        _G_s = nx.MultiDiGraph()
        for u, v, n, d in G_s.edges(data=True, keys=True):
            if d[score] > th:
                _G_s.add_edge(u, v, n, **d)
        _G_s.add_nodes_from(G_s.nodes(data=True))

        edges = nx.to_pandas_edgelist(_G_s)
        if len(edges) < 1:
            fig = dict()
            return fig
        # add same color scheme as network graph
        for node_s in _G_s.nodes():
            if " Post" in node_s:
                original_node = str(node_s).split(sep=" Post")[1]
            elif "Pre " in node_s:
                original_node = str(node_s).split(sep="Pre ")[1]
            else:
                original_node = str(node_s)

            new_color = color_map_nodes[original_node.strip()]
            G_s.nodes[node_s]["color"] = new_color

        nodes = G_s.nodes()

        node_map = {cluster: id for id, cluster in enumerate(list(nodes))}

        sankey = go.Sankey(node=dict(pad=15,
                                     thickness=20,
                                     line=dict(color="black", width=0.5),
                                     label=list(nodes),
                                     color=[
                                         f'rgb{tuple(d["color"][0:3])}'
                                         for n, d in G_s.nodes(data=True)
                                     ]),
                           link=dict(
                               source=list(edges["source"].map(node_map)),
                               target=list(edges["target"].map(node_map)),
                               value=list(edges[score]),
                               label=edges["interaction"]))

        data = [sankey]

        layout = go.Layout(autosize=True,
                           title=f"Interactions: {node}",
                           font=dict(size=font_size))

        fig = go.Figure(data=data, layout=layout)

        return fig

    @app.callback(
        [Output("ligand-table", "columns"),
         Output("ligand-table", "data")], [
             Input("ligand-graph", "figure"),
             Input("ligand-graph", "selectedData")
         ])
    def select_ligands(figure, selected):
        import json
        ligands = []
        score = []
        zscore = []
        pval = []

        for group in figure["data"]:
            for ligand in group["hovertext"]:
                ligands.append(ligand)
            for data in group["customdata"]:
                score.append(data[0])
                zscore.append(data[1])
                pval.append(data[2])

        df = pd.DataFrame({
            "Ligand": ligands,
            "Score": score,
            "Z-score": zscore,
            "P-value": pval
        })
        df.index = df["Ligand"]
        df.sort_values(by="Score", ascending=False, inplace=True)

        if isinstance(selected, dict):
            filt = []
            for point in selected["points"]:
                filt.append(point["hovertext"])
            df = df.loc[filt]

        columns = [{
            "name": "Ligand",
            "id": "Ligand"
        }, {
            "name": "Score",
            "id": "Score"
        }, {
            "name": "Z-score",
            "id": "Z-score"
        }, {
            "name": "P-value",
            "id": "P-value"
        }]

        data = df.to_dict("records")

        return columns, data

    @app.callback([
        Output("receptor-table", "columns"),
        Output("receptor-table", "data")
    ], [
        Input("receptor-graph", "figure"),
        Input("receptor-graph", "selectedData")
    ])
    def select_ligands(figure, selected):
        import json
        receptors = []
        score = []
        zscore = []
        pval = []

        for group in figure["data"]:
            for receptor in group["hovertext"]:
                receptors.append(receptor)
            for data in group["customdata"]:
                score.append(data[0])
                zscore.append(data[1])
                pval.append(data[2])

        df = pd.DataFrame({
            "Receptor": receptors,
            "Score": score,
            "Z-score": zscore,
            "P-value": pval
        })
        df.index = df["Receptor"]
        df.sort_values(by="Score", ascending=False, inplace=True)

        if isinstance(selected, dict):
            filt = []
            for point in selected["points"]:
                filt.append(point["hovertext"])
            df = df.loc[filt]

        columns = [{
            "name": "Receptor",
            "id": "Receptor"
        }, {
            "name": "Score",
            "id": "Score"
        }, {
            "name": "Z-score",
            "id": "Z-score"
        }, {
            "name": "P-value",
            "id": "P-value"
        }]

        data = df.to_dict("records")

        return columns, data

    # Run server
    app.run_server(**kwargs)
Ejemplo n.º 10
0
    def __init__(self, input_graph, app_display='default'):
        """
        Initialises the DashGraph object from the Graph class object.
        Dash creates a mini Flask server to visualise the graphs.

        :param app_display: (str) 'default' by default and 'jupyter notebook' for running Dash inside Jupyter Notebook.
        :param input_graph: (Graph) Graph class from graph.py.
        """
        self.graph = None
        # Dash app styling with Bootstrap
        if app_display == 'jupyter notebook':
            self.app = JupyterDash(__name__,
                                   external_stylesheets=[dbc.themes.BOOTSTRAP])
        else:
            self.app = Dash(__name__,
                            external_stylesheets=[dbc.themes.BOOTSTRAP])

        # Graph class object
        self.graph = input_graph
        # The dictionary of the nodes coordinates
        self.pos = self.graph.get_pos()

        # Colours of nodes
        self.colour_groups = {}
        # If colours have been assigned in Graph class, add styling
        if self.graph.get_node_colours():
            colour_map = self.graph.get_node_colours()
            self._assign_colours_to_groups(list(colour_map.keys()))

        self.weights = []
        self.elements = []
        self._update_elements()

        # Load the different graph layouts
        cyto.load_extra_layouts()
        self.layout_options = ['cose-bilkent', 'cola', 'spread']
        self.statistics = [
            'graph_summary', 'average_degree_connectivity',
            'average_neighbor_degree', 'betweenness_centrality'
        ]
        # Load default stylesheet
        self.stylesheet = None
        self.stylesheet = self._get_default_stylesheet()

        # Append stylesheet for colour and size
        # If sizes have been set in the Graph class
        self._style_colours()
        if self.graph.get_node_sizes():
            self._assign_sizes()

        self.cyto_graph = None

        # Callback functions to hook frontend elements to functions
        self.app.callback(Output('cytoscape', 'layout'),
                          [Input('dropdown-layout', 'value')])(
                              DashGraph._update_cytoscape_layout)
        self.app.callback(Output('json-output', 'children'),
                          [Input('dropdown-stat', 'value')])(
                              self._update_stat_json)
        self.app.callback(Output('cytoscape', 'elements'),
                          [Input('rounding_decimals', 'value')])(
                              self._round_decimals)
Ejemplo n.º 11
0
def loadextralayouts():
    import dash_cytoscape as cyto
    cyto.load_extra_layouts()  # Load extra layouts