plottest / app.py
eaglelandsonce's picture
Update app.py
ffc369c verified
import streamlit as st
import streamlit.components.v1 as components
# Set page config
st.set_page_config(page_title="Precision Medicine Network", layout="wide")
# Title
st.title("Precision Medicine Network")
# HTML content (previous D3.js visualization)
html_content = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Precision Medicine Network</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>
<style>
#graph { width: 100%; height: 600px; border: 1px solid #ccc; position: relative; }
.popup {
position: absolute;
background: white;
border: 1px solid #999;
border-radius: 4px;
padding: 10px;
display: none;
}
</style>
</head>
<body>
<div id="graph"></div>
<div id="popup" class="popup"></div>
<script>
const width = 800;
const height = 600;
const svg = d3.select("#graph")
.append("svg")
.attr("width", width)
.attr("height", height);
const simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(d => d.id))
.force("charge", d3.forceManyBody().strength(-50))
.force("center", d3.forceCenter(width / 2, height / 2));
const nodes = [];
const links = [];
// Create nodes for healthcare professionals
const doctors = 5;
const nurses = 10;
const clinicians = 8;
for (let i = 0; i < doctors; i++) {
nodes.push({ id: `Doctor${i + 1}`, group: "doctor" });
}
for (let i = 0; i < nurses; i++) {
nodes.push({ id: `Nurse${i + 1}`, group: "nurse" });
}
for (let i = 0; i < clinicians; i++) {
nodes.push({ id: `Clinician${i + 1}`, group: "clinician" });
}
// Create nodes for patients
for (let i = 0; i < 100; i++) {
nodes.push({ id: `Patient${i + 1}`, group: "patient" });
}
// Create links between patients and healthcare professionals
nodes.filter(n => n.group === "patient").forEach(patient => {
const doctor = nodes.find(n => n.group === "doctor" && Math.random() < 0.2);
if (doctor) links.push({ source: patient.id, target: doctor.id });
const nurse = nodes.find(n => n.group === "nurse" && Math.random() < 0.3);
if (nurse) links.push({ source: patient.id, target: nurse.id });
const clinician = nodes.find(n => n.group === "clinician" && Math.random() < 0.25);
if (clinician) links.push({ source: patient.id, target: clinician.id });
});
const link = svg.append("g")
.selectAll("line")
.data(links)
.enter().append("line")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6);
const node = svg.append("g")
.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("r", d => d.group === "patient" ? 3 : 5)
.attr("fill", d => {
switch (d.group) {
case "doctor": return "#ff0000";
case "nurse": return "#00ff00";
case "clinician": return "#0000ff";
default: return "#cccccc";
}
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.on("click", showPopup);
simulation
.nodes(nodes)
.on("tick", ticked);
simulation.force("link")
.links(links);
function ticked() {
link
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y);
node
.attr("cx", d => d.x)
.attr("cy", d => d.y);
}
function dragstarted(event) {
if (!event.active) simulation.alphaTarget(0.3).restart();
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
}
function dragged(event) {
event.subject.fx = event.x;
event.subject.fy = event.y;
}
function dragended(event) {
if (!event.active) simulation.alphaTarget(0);
event.subject.fx = null;
event.subject.fy = null;
}
function showPopup(event, d) {
const popup = d3.select("#popup");
popup.style("display", "block")
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 10) + "px")
.html(`<strong>ID:</strong> ${d.id}<br><strong>Role:</strong> ${d.group}`);
// Hide popup when clicking elsewhere
d3.select("body").on("click", function() {
if (event.target.tagName !== "circle") {
popup.style("display", "none");
}
});
}
</script>
</body>
</html>
"""
# Embed the HTML content
components.html(html_content, height=650)
# Add some explanation
st.markdown("""
This graph represents a precision medicine network with the following components:
- 5 Doctors (red nodes)
- 10 Nurses (green nodes)
- 8 Clinicians (blue nodes)
- 100 Patients (gray nodes)
The connections between patients and healthcare professionals are generated randomly with the following probabilities:
- 20% chance for a patient to be connected to a doctor
- 30% chance for a patient to be connected to a nurse
- 25% chance for a patient to be connected to a clinician
You can interact with the graph by:
- Dragging nodes to rearrange the layout
- Clicking on a node to see its ID and role
""")