ProfRick commited on
Commit
d691bd4
·
verified ·
1 Parent(s): 8644841

Create app.py

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