Spaces:
Running
Running
File size: 7,313 Bytes
d691bd4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# -*- coding: utf-8 -*-
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
st.set_page_config(page_title="Homeostasis Explorer", layout="centered")
# -----------------------------
# Systems with disturbance-specific roles
# -----------------------------
SYSTEMS = {
"Glucose": {
"setpoint": 90.0,
"units": "mg/dL",
"events": {
"Meal (carbs) – hyperglycemia": {
"disturbance_magnitude": +40.0,
"roles": {
"Sensor": "Pancreatic β-cells (detect ↑ glucose)",
"Control Center": "Pancreatic β-cells (insulin secretion)",
"Effector(s)": "Insulin → liver (↑glycogenesis, ↓gluconeogenesis), muscle/adipose (↑GLUT4 uptake)"
},
"note": "Hyperglycemia evokes insulin to lower glucose."
},
"Light exercise / fasting – hypoglycemia": {
"disturbance_magnitude": -20.0,
"roles": {
"Sensor": "Pancreatic α-cells (detect ↓ glucose)",
"Control Center": "Pancreatic α-cells (glucagon secretion)",
"Effector(s)": "Glucagon → liver (↑glycogenolysis, ↑gluconeogenesis); adipose (↑lipolysis)"
},
"note": "Hypoglycemia evokes glucagon and counter-regulatory hormones to raise glucose."
}
},
"k_time_constant": 6.0,
"feedback_gain": 0.35
},
"Temperature": {
"setpoint": 37.0,
"units": "°C",
"events": {
"Cold exposure (↓T)": {
"disturbance_magnitude": -5.0,
"roles": {
"Sensor": "Peripheral & central thermoreceptors (detect ↓temp)",
"Control Center": "Hypothalamus (thermoregulatory center)",
"Effector(s)": "Shivering, cutaneous vasoconstriction, (± brown fat thermogenesis)"
},
"note": "Cold evokes heat production & conservation."
},
"Heat exposure (↑T)": {
"disturbance_magnitude": +2.5,
"roles": {
"Sensor": "Peripheral & central thermoreceptors (detect ↑temp)",
"Control Center": "Hypothalamus",
"Effector(s)": "Sweating, cutaneous vasodilation"
},
"note": "Heat evokes heat dissipation."
}
},
"k_time_constant": 5.0,
"feedback_gain": 0.40
},
"Blood Pressure (MAP)": {
"setpoint": 95.0,
"units": "mmHg (~MAP)",
"events": {
"Standing quickly (orthostatic ↓MAP)": {
"disturbance_magnitude": -15.0,
"roles": {
"Sensor": "Baroreceptors (carotid sinus, aortic arch) sense ↓ stretch",
"Control Center": "Medullary cardiovascular centers",
"Effector(s)": "↑HR, ↑contractility, arteriolar vasoconstriction, venoconstriction"
},
"note": "Baroreflex counters an acute drop in MAP."
},
"Pain/startle (↑MAP surge)": {
"disturbance_magnitude": +10.0,
"roles": {
"Sensor": "Baroreceptors sense ↑ stretch",
"Control Center": "Medullary cardiovascular centers",
"Effector(s)": "↑Vagal tone/↓sympathetic tone → ↓HR, ↓contractility, vasodilation"
},
"note": "Baroreflex counters an acute rise in MAP."
}
},
"k_time_constant": 4.5,
"feedback_gain": 0.45
},
"pH": {
"setpoint": 7.40,
"units": "pH",
"events": {
"Hypoventilation (resp. acidosis tendency)": {
"disturbance_magnitude": -0.10,
"roles": {
"Sensor": "Central & peripheral chemoreceptors (↑CO₂/H⁺)",
"Control Center": "Medullary respiratory centers",
"Effector(s)": "↑Ventilation (↑RR and/or tidal volume) to blow off CO₂"
},
"note": "Ventilation rapidly raises pH back toward 7.4."
},
"Hyperventilation (resp. alkalosis tendency)": {
"disturbance_magnitude": +0.10,
"roles": {
"Sensor": "Central & peripheral chemoreceptors (↓CO₂/H⁺)",
"Control Center": "Medullary respiratory centers",
"Effector(s)": "↓Ventilation (↓RR and/or tidal volume) to retain CO₂"
},
"note": "Ventilation lowers pH back toward 7.4."
}
},
"k_time_constant": 3.5,
"feedback_gain": 0.50
}
}
# -----------------------------------
# Simple negative-feedback model
# x' = D(t) - k*(x - set) - g*(x - set)
# -----------------------------------
def simulate(system_name, event_name, duration=60.0, dt=0.1):
sys = SYSTEMS[system_name]
setpoint = sys["setpoint"]
k = 1.0 / sys["k_time_constant"]
g = sys["feedback_gain"]
t = np.arange(0.0, duration + dt, dt)
x = np.ones_like(t) * setpoint
D = np.zeros_like(t)
mag = sys["events"][event_name]["disturbance_magnitude"]
D[(t >= 5.0) & (t < 15.0)] = mag
for i in range(1, len(t)):
error = x[i-1] - setpoint
feedback = -g * error
dxdt = D[i-1] - k*error + feedback
x[i] = x[i-1] + dxdt * dt
return t, x, setpoint, sys["units"]
# -----------------------------
# Streamlit UI
# -----------------------------
st.title("Homeostasis Explorer: Negative Feedback")
st.markdown(
"""Select a **System** and a **Disturbance**, then click **Run Simulation**.
Roles update based on the disturbance; the plot shows the variable returning toward its set point."""
)
# Controls
system = st.selectbox("System", list(SYSTEMS.keys()), index=0)
event = st.selectbox("Disturbance", list(SYSTEMS[system]["events"].keys()), index=0)
# Run button with initial auto-render
if "init" not in st.session_state:
st.session_state.init = True
run = st.button("Run Simulation")
if st.session_state.init or run:
st.session_state.init = False
t, x, setpoint, units = simulate(system, event, duration=60.0, dt=0.1)
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot(t, x, label="Observed variable")
ax.axhline(setpoint, linestyle="--", label=f"Set point = {setpoint} {units}")
ax.axvspan(5.0, 15.0, alpha=0.1, label="Disturbance window")
ax.set_xlabel("Time (a.u.)")
ax.set_ylabel(f"{system} ({units})")
ax.set_title(f"{system} response to: {event}")
ax.legend(loc="best")
st.pyplot(fig)
roles = SYSTEMS[system]["events"][event]["roles"]
note = SYSTEMS[system]["events"][event]["note"]
st.subheader(f"Feedback Roles — _{event}_")
st.markdown(
f"- **Sensor:** {roles['Sensor']}\n"
f"- **Control Center:** {roles['Control Center']}\n"
f"- **Effector(s):** {roles['Effector(s)']}"
)
st.caption(f"*Note:* {note}")
st.info("Tip: Adjust the selections and click **Run Simulation** again to compare responses.")
|