streamlit-cytoscape / src /streamlit_app.py
kozo2's picture
Upload src/streamlit_app.py with huggingface_hub
015baef verified
raw
history blame
3.83 kB
import json
import random
import streamlit as st
import streamlit.components.v1 as components
# --- CONFIGURATION -------------------------------------------------------------
HEIGHT = 600
DEFAULT_NODES = 10
DEFAULT_EDGES = 12
# --- HELPER FUNCTIONS ----------------------------------------------------------
def random_rgb():
return "#{:02x}{:02x}{:02x}".format(
random.randint(50, 200),
random.randint(50, 200),
random.randint(50, 200)
)
def build_cytoscape_elements(n_nodes, n_edges):
"""Return Cytoscape-compatible elements JSON."""
nodes = [{"data": {"id": str(i), "label": f"Node {i}"}} for i in range(n_nodes)]
edges = [
{
"data": {
"id": f"{u}-{v}",
"source": str(u),
"target": str(v),
"weight": random.randint(1, 5),
}
}
for u, v in [random.sample(range(n_nodes), 2) for _ in range(n_edges)]
]
return nodes + edges
def build_html(elements_json, height):
"""Return complete HTML/JS string for standalone Cytoscape viewer."""
background_color = random_rgb()
return f"""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cytoscape.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/dagre.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/cytoscape-dagre.js"></script>
<style>
html, body {{{{ margin: 0; height: 100%; }}}}
#cy {{{{ width: 100%; height: {height}px; border: 1px solid #ccc; }}}}
</style>
</head>
<body>
<div id="cy"></div>
<script>
// Register dagre layout extension
if (typeof cytoscape !== 'undefined' && typeof cytoscape.use === 'function' && typeof dagre !== 'undefined') {{
cytoscape.use(cytoscapeDagre);
}}
const elements = {elements_json};
const cy = cytoscape({{
container: document.getElementById('cy'),
elements: elements,
style: [
{{
selector: 'node',
style: {{
'label': 'data(label)',
'background-color': '{background_color}',
'text-valign': 'center',
'color': '#fff',
'font-size': 12
}}
}},
{{
selector: 'edge',
style: {{
'width': 'mapData(weight, 1, 5, 1, 5)',
'line-color': '#bbb',
'target-arrow-color': '#bbb',
'curve-style': 'bezier',
'target-arrow-shape': 'triangle'
}}
}}
]
}});
// Apply layout after elements are added
cy.layout({{ name: 'dagre', rankDir: 'LR' }}).run();
// Resize handling for Streamlit container
window.addEventListener('resize', () => cy.resize());
</script>
</body>
</html>
"""
# --- STREAMLIT UI --------------------------------------------------------------
st.set_page_config(page_title="Cytoscape + Streamlit Demo", layout="wide")
st.title("Cytoscape Network Viewer in Streamlit")
with st.sidebar:
st.header("Controls")
n_nodes = st.slider("Nodes", 3, 50, DEFAULT_NODES)
n_edges = st.slider("Edges", max(1, n_nodes - 1), 100, DEFAULT_EDGES)
if st.button("Regenerate"):
st.cache_data.clear()
# --- RENDER CYTOSCAPE ----------------------------------------------------------
elements = build_cytoscape_elements(n_nodes, n_edges)
html = build_html(json.dumps(elements), HEIGHT)
components.html(html, height=HEIGHT)