Sephfox commited on
Commit
5041924
·
verified ·
1 Parent(s): a8de614

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -110
app.py CHANGED
@@ -4,30 +4,18 @@ import streamlit as st
4
  import plotly.graph_objects as go
5
  from plotly.subplots import make_subplots
6
  import time
7
- import threading
8
- import queue
9
-
10
-
11
-
12
- # Your classes and functions...
13
 
14
  class Organelle:
15
  def __init__(self, type):
16
  self.type = type
17
 
18
- class Modification:
19
- def __init__(self, name, effect):
20
- self.name = name
21
- self.effect = effect
22
-
23
  class Cell:
24
  def __init__(self, x, y, cell_type="prokaryote"):
25
  self.x = x
26
  self.y = y
27
  self.energy = 100
28
  self.cell_type = cell_type
29
- self.organelles = []
30
- self.modifications = []
31
  self.size = 1
32
  self.color = "lightblue"
33
  self.division_threshold = 150
@@ -36,33 +24,32 @@ class Cell:
36
 
37
  def update_properties(self):
38
  if self.cell_type == "early_eukaryote":
39
- self.organelles.append(Organelle("nucleus"))
40
  self.color = "green"
41
  self.size = 2
42
  elif self.cell_type == "advanced_eukaryote":
43
- self.organelles.extend([Organelle("nucleus"), Organelle("mitochondria")])
44
  self.color = "red"
45
  self.size = 3
46
  elif self.cell_type == "plant_like":
47
- self.organelles.extend([Organelle("nucleus"), Organelle("mitochondria"), Organelle("chloroplast")])
48
  self.color = "darkgreen"
49
  self.size = 4
 
 
 
 
50
 
51
  def move(self, environment):
52
- dx = random.uniform(-1, 1)
53
- dy = random.uniform(-1, 1)
54
  self.x = max(0, min(environment.width - 1, self.x + dx))
55
  self.y = max(0, min(environment.height - 1, self.y + dy))
56
  self.energy -= 0.5 * self.size
57
 
58
  def feed(self, environment):
59
  base_energy = environment.grid[int(self.y)][int(self.x)] * 0.1
60
- if "chloroplast" in [org.type for org in self.organelles]:
61
  base_energy += environment.light_level * 2
62
-
63
- for mod in self.modifications:
64
- base_energy *= mod.effect
65
-
66
  self.energy += base_energy
67
  environment.grid[int(self.y)][int(self.x)] *= 0.9
68
 
@@ -74,7 +61,6 @@ class Cell:
74
  self.energy /= 2
75
  new_cell = Cell(self.x, self.y, self.cell_type)
76
  new_cell.organelles = self.organelles.copy()
77
- new_cell.modifications = self.modifications.copy()
78
  return new_cell
79
  return None
80
 
@@ -88,30 +74,17 @@ class Cell:
88
  new_cell_type = "early_eukaryote"
89
  elif self.cell_type == "early_eukaryote":
90
  new_cell_type = "advanced_eukaryote"
 
 
 
 
91
 
92
- new_cell = Cell(
93
- (self.x + other.x) / 2,
94
- (self.y + other.y) / 2,
95
- new_cell_type
96
- )
97
  new_cell.energy = self.energy + other.energy
98
- new_cell.organelles = list(set(self.organelles + other.organelles))
99
- new_cell.modifications = list(set(self.modifications + other.modifications))
100
  new_cell.update_properties()
101
  return new_cell
102
 
103
- def acquire_modification(self):
104
- possible_mods = [
105
- Modification("Enhanced metabolism", 1.2),
106
- Modification("Thick cell wall", 0.8),
107
- Modification("Efficient energy storage", 1.1),
108
- Modification("Rapid division", 0.9)
109
- ]
110
- new_mod = random.choice(possible_mods)
111
- if new_mod not in self.modifications:
112
- self.modifications.append(new_mod)
113
- self.color = "purple" # Visual indicator of modification
114
-
115
  class Environment:
116
  def __init__(self, width, height):
117
  self.width = width
@@ -122,7 +95,7 @@ class Environment:
122
  self.time = 0
123
  self.population_history = {
124
  "prokaryote": [], "early_eukaryote": [],
125
- "advanced_eukaryote": [], "plant_like": [], "modified": []
126
  }
127
 
128
  def add_cell(self, cell):
@@ -159,102 +132,89 @@ class Environment:
159
  self.cells.extend(new_cells)
160
  self.cells = [cell for cell in self.cells if cell not in cells_to_remove]
161
 
162
- # Introduce mutations and modifications
163
- for cell in self.cells:
164
- if random.random() < 0.0001: # 0.01% chance of mutation
165
- if cell.cell_type == "early_eukaryote":
166
- cell.cell_type = "advanced_eukaryote"
167
- elif cell.cell_type == "advanced_eukaryote" and random.random() < 0.5:
168
- cell.cell_type = "plant_like"
169
- cell.update_properties()
170
-
171
- if random.random() < 0.0005: # 0.05% chance of acquiring a modification
172
- cell.acquire_modification()
173
-
174
  # Record population counts
175
  for cell_type in self.population_history.keys():
176
- if cell_type != "modified":
177
- count = len([cell for cell in self.cells if cell.cell_type == cell_type and not cell.modifications])
178
- else:
179
- count = len([cell for cell in self.cells if cell.modifications])
180
  self.population_history[cell_type].append(count)
181
 
182
  def get_visualization_data(self):
183
- cell_data = {
184
- "prokaryote": {"x": [], "y": [], "size": [], "color": "lightblue", "symbol": "circle"},
185
- "early_eukaryote": {"x": [], "y": [], "size": [], "color": "green", "symbol": "square"},
186
- "advanced_eukaryote": {"x": [], "y": [], "size": [], "color": "red", "symbol": "diamond"},
187
- "plant_like": {"x": [], "y": [], "size": [], "color": "darkgreen", "symbol": "star"},
188
- "modified": {"x": [], "y": [], "size": [], "color": "purple", "symbol": "cross"}
189
- }
190
 
191
  for cell in self.cells:
192
- cell_type = "modified" if cell.modifications else cell.cell_type
193
- cell_data[cell_type]["x"].append(cell.x)
194
- cell_data[cell_type]["y"].append(cell.y)
195
- cell_data[cell_type]["size"].append(cell.size * 3)
196
 
197
- return cell_data, self.population_history
198
 
199
  def setup_figure(env):
200
- cell_types = ["prokaryote", "early_eukaryote", "advanced_eukaryote", "plant_like", "modified"]
201
- fig = make_subplots(rows=2, cols=3,
202
  subplot_titles=("Cell Distribution", "Total Population",
203
- "Prokaryotes", "Early Eukaryotes",
204
- "Advanced Eukaryotes", "Plant-like & Modified"),
205
  vertical_spacing=0.1,
206
  horizontal_spacing=0.05)
207
 
 
 
208
  # Cell distribution
209
- for cell_type, data in env.get_visualization_data()[0].items():
210
  fig.add_trace(go.Scatter(
211
  x=data["x"], y=data["y"], mode='markers',
212
- marker=dict(color=data["color"], size=data["size"], symbol=data["symbol"]),
213
  name=cell_type
214
  ), row=1, col=1)
215
 
216
  # Total population over time
217
- for cell_type, counts in env.population_history.items():
218
- fig.add_trace(go.Scatter(y=counts, mode='lines', name=cell_type), row=1, col=2)
219
-
220
- # Individual population charts
221
- for i, cell_type in enumerate(cell_types):
222
- if cell_type == "modified":
223
- fig.add_trace(go.Scatter(y=env.population_history[cell_type], mode='lines',
224
- name=cell_type, line=dict(color="purple")), row=2, col=3)
225
- elif cell_type == "plant_like":
226
- fig.add_trace(go.Scatter(y=env.population_history[cell_type], mode='lines',
227
- name=cell_type, line=dict(color="darkgreen")), row=2, col=3)
228
- else:
229
- fig.add_trace(go.Scatter(y=env.population_history[cell_type], mode='lines',
230
- name=cell_type), row=2, col=i+1)
231
 
232
  fig.update_xaxes(title_text="X", row=1, col=1)
233
  fig.update_yaxes(title_text="Y", row=1, col=1)
234
  fig.update_xaxes(title_text="Time", row=1, col=2)
235
  fig.update_yaxes(title_text="Population", row=1, col=2)
236
-
237
- for i in range(1, 4):
238
- fig.update_xaxes(title_text="Time", row=2, col=i)
239
- fig.update_yaxes(title_text="Population", row=2, col=i)
240
 
241
  fig.update_layout(height=800, width=1200, title_text="Advanced Cell Evolution Simulation")
242
 
243
  return fig
244
 
245
- # Create a queue to communicate between the threads
246
- q = queue.Queue()
247
-
248
  # Streamlit app
249
  st.title("Advanced Cell Evolution Simulation")
250
 
251
  initial_cells = st.slider("Initial number of cells", 10, 200, 100)
252
  update_interval = st.slider("Update interval (seconds)", 0.1, 5.0, 1.0)
253
 
254
- # Create a placeholder for the chart
255
  chart_placeholder = st.empty()
 
 
 
 
 
 
 
 
256
 
257
- if st.button("Start Simulation"):
 
 
258
  env = Environment(100, 100)
259
  for _ in range(initial_cells):
260
  cell = Cell(random.uniform(0, env.width), random.uniform(0, env.height))
@@ -262,23 +222,40 @@ if st.button("Start Simulation"):
262
 
263
  fig = setup_figure(env)
264
 
265
- for _ in range(100): # Run for 100 steps
266
  env.update()
267
 
268
  with fig.batch_update():
269
- cell_data, population_history = env.get_visualization_data()
 
 
270
  for i, (cell_type, data) in enumerate(cell_data.items()):
271
  fig.data[i].x = data["x"]
272
  fig.data[i].y = data["y"]
273
  fig.data[i].marker.size = data["size"]
274
 
 
 
 
 
 
275
  for i, (cell_type, counts) in enumerate(population_history.items()):
276
- fig.data[i+5].y = counts
277
- if cell_type != "modified" and cell_type != "plant_like":
278
- fig.data[i+10].y = counts
279
- else:
280
- fig.data[13].y = population_history["plant_like"]
281
- fig.data[14].y = population_history["modified"]
 
 
282
 
283
  chart_placeholder.plotly_chart(fig, use_container_width=True)
284
- time.sleep(update_interval)
 
 
 
 
 
 
 
 
 
4
  import plotly.graph_objects as go
5
  from plotly.subplots import make_subplots
6
  import time
 
 
 
 
 
 
7
 
8
  class Organelle:
9
  def __init__(self, type):
10
  self.type = type
11
 
 
 
 
 
 
12
  class Cell:
13
  def __init__(self, x, y, cell_type="prokaryote"):
14
  self.x = x
15
  self.y = y
16
  self.energy = 100
17
  self.cell_type = cell_type
18
+ self.organelles = set()
 
19
  self.size = 1
20
  self.color = "lightblue"
21
  self.division_threshold = 150
 
24
 
25
  def update_properties(self):
26
  if self.cell_type == "early_eukaryote":
27
+ self.organelles.add("nucleus")
28
  self.color = "green"
29
  self.size = 2
30
  elif self.cell_type == "advanced_eukaryote":
31
+ self.organelles.update(["nucleus", "mitochondria"])
32
  self.color = "red"
33
  self.size = 3
34
  elif self.cell_type == "plant_like":
35
+ self.organelles.update(["nucleus", "mitochondria", "chloroplast"])
36
  self.color = "darkgreen"
37
  self.size = 4
38
+ elif self.cell_type == "complete":
39
+ self.organelles.update(["nucleus", "mitochondria", "chloroplast", "endoplasmic_reticulum", "golgi_apparatus"])
40
+ self.color = "purple"
41
+ self.size = 5
42
 
43
  def move(self, environment):
44
+ dx, dy = random.uniform(-1, 1), random.uniform(-1, 1)
 
45
  self.x = max(0, min(environment.width - 1, self.x + dx))
46
  self.y = max(0, min(environment.height - 1, self.y + dy))
47
  self.energy -= 0.5 * self.size
48
 
49
  def feed(self, environment):
50
  base_energy = environment.grid[int(self.y)][int(self.x)] * 0.1
51
+ if "chloroplast" in self.organelles:
52
  base_energy += environment.light_level * 2
 
 
 
 
53
  self.energy += base_energy
54
  environment.grid[int(self.y)][int(self.x)] *= 0.9
55
 
 
61
  self.energy /= 2
62
  new_cell = Cell(self.x, self.y, self.cell_type)
63
  new_cell.organelles = self.organelles.copy()
 
64
  return new_cell
65
  return None
66
 
 
74
  new_cell_type = "early_eukaryote"
75
  elif self.cell_type == "early_eukaryote":
76
  new_cell_type = "advanced_eukaryote"
77
+ elif self.cell_type == "advanced_eukaryote":
78
+ new_cell_type = "plant_like"
79
+ elif self.cell_type == "plant_like":
80
+ new_cell_type = "complete"
81
 
82
+ new_cell = Cell((self.x + other.x) / 2, (self.y + other.y) / 2, new_cell_type)
 
 
 
 
83
  new_cell.energy = self.energy + other.energy
84
+ new_cell.organelles = self.organelles.union(other.organelles)
 
85
  new_cell.update_properties()
86
  return new_cell
87
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  class Environment:
89
  def __init__(self, width, height):
90
  self.width = width
 
95
  self.time = 0
96
  self.population_history = {
97
  "prokaryote": [], "early_eukaryote": [],
98
+ "advanced_eukaryote": [], "plant_like": [], "complete": []
99
  }
100
 
101
  def add_cell(self, cell):
 
132
  self.cells.extend(new_cells)
133
  self.cells = [cell for cell in self.cells if cell not in cells_to_remove]
134
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  # Record population counts
136
  for cell_type in self.population_history.keys():
137
+ count = len([cell for cell in self.cells if cell.cell_type == cell_type])
 
 
 
138
  self.population_history[cell_type].append(count)
139
 
140
  def get_visualization_data(self):
141
+ cell_data = {cell_type: {"x": [], "y": [], "size": []} for cell_type in self.population_history.keys()}
142
+ colors = {"prokaryote": "lightblue", "early_eukaryote": "green", "advanced_eukaryote": "red", "plant_like": "darkgreen", "complete": "purple"}
 
 
 
 
 
143
 
144
  for cell in self.cells:
145
+ cell_data[cell.cell_type]["x"].append(cell.x)
146
+ cell_data[cell.cell_type]["y"].append(cell.y)
147
+ cell_data[cell.cell_type]["size"].append(cell.size * 3)
 
148
 
149
+ return cell_data, self.population_history, colors
150
 
151
  def setup_figure(env):
152
+ cell_types = list(env.population_history.keys())
153
+ fig = make_subplots(rows=2, cols=2,
154
  subplot_titles=("Cell Distribution", "Total Population",
155
+ "Population by Cell Type", "Organelle Distribution"),
 
156
  vertical_spacing=0.1,
157
  horizontal_spacing=0.05)
158
 
159
+ cell_data, population_history, colors = env.get_visualization_data()
160
+
161
  # Cell distribution
162
+ for cell_type, data in cell_data.items():
163
  fig.add_trace(go.Scatter(
164
  x=data["x"], y=data["y"], mode='markers',
165
+ marker=dict(color=colors[cell_type], size=data["size"]),
166
  name=cell_type
167
  ), row=1, col=1)
168
 
169
  # Total population over time
170
+ total_population = [sum(counts) for counts in zip(*population_history.values())]
171
+ fig.add_trace(go.Scatter(y=total_population, mode='lines', name="Total"), row=1, col=2)
172
+
173
+ # Population by cell type
174
+ for cell_type, counts in population_history.items():
175
+ fig.add_trace(go.Scatter(y=counts, mode='lines', name=cell_type, line=dict(color=colors[cell_type])), row=2, col=1)
176
+
177
+ # Organelle distribution
178
+ organelle_counts = {"nucleus": 0, "mitochondria": 0, "chloroplast": 0, "endoplasmic_reticulum": 0, "golgi_apparatus": 0}
179
+ for cell in env.cells:
180
+ for organelle in cell.organelles:
181
+ organelle_counts[organelle] += 1
182
+
183
+ fig.add_trace(go.Bar(x=list(organelle_counts.keys()), y=list(organelle_counts.values()), name="Organelles"), row=2, col=2)
184
 
185
  fig.update_xaxes(title_text="X", row=1, col=1)
186
  fig.update_yaxes(title_text="Y", row=1, col=1)
187
  fig.update_xaxes(title_text="Time", row=1, col=2)
188
  fig.update_yaxes(title_text="Population", row=1, col=2)
189
+ fig.update_xaxes(title_text="Time", row=2, col=1)
190
+ fig.update_yaxes(title_text="Population", row=2, col=1)
191
+ fig.update_xaxes(title_text="Organelle", row=2, col=2)
192
+ fig.update_yaxes(title_text="Count", row=2, col=2)
193
 
194
  fig.update_layout(height=800, width=1200, title_text="Advanced Cell Evolution Simulation")
195
 
196
  return fig
197
 
 
 
 
198
  # Streamlit app
199
  st.title("Advanced Cell Evolution Simulation")
200
 
201
  initial_cells = st.slider("Initial number of cells", 10, 200, 100)
202
  update_interval = st.slider("Update interval (seconds)", 0.1, 5.0, 1.0)
203
 
204
+ # Create placeholders for the chart and stop button
205
  chart_placeholder = st.empty()
206
+ stop_button_placeholder = st.empty()
207
+
208
+ # Initialize session state
209
+ if 'running' not in st.session_state:
210
+ st.session_state.running = False
211
+
212
+ def toggle_simulation():
213
+ st.session_state.running = not st.session_state.running
214
 
215
+ start_stop_button = st.button("Start/Stop Simulation", on_click=toggle_simulation)
216
+
217
+ if st.session_state.running:
218
  env = Environment(100, 100)
219
  for _ in range(initial_cells):
220
  cell = Cell(random.uniform(0, env.width), random.uniform(0, env.height))
 
222
 
223
  fig = setup_figure(env)
224
 
225
+ while st.session_state.running:
226
  env.update()
227
 
228
  with fig.batch_update():
229
+ cell_data, population_history, colors = env.get_visualization_data()
230
+
231
+ # Update cell distribution
232
  for i, (cell_type, data) in enumerate(cell_data.items()):
233
  fig.data[i].x = data["x"]
234
  fig.data[i].y = data["y"]
235
  fig.data[i].marker.size = data["size"]
236
 
237
+ # Update total population
238
+ total_population = [sum(counts) for counts in zip(*population_history.values())]
239
+ fig.data[len(cell_data)].y = total_population
240
+
241
+ # Update population by cell type
242
  for i, (cell_type, counts) in enumerate(population_history.items()):
243
+ fig.data[len(cell_data) + 1 + i].y = counts
244
+
245
+ # Update organelle distribution
246
+ organelle_counts = {"nucleus": 0, "mitochondria": 0, "chloroplast": 0, "endoplasmic_reticulum": 0, "golgi_apparatus": 0}
247
+ for cell in env.cells:
248
+ for organelle in cell.organelles:
249
+ organelle_counts[organelle] += 1
250
+ fig.data[-1].y = list(organelle_counts.values())
251
 
252
  chart_placeholder.plotly_chart(fig, use_container_width=True)
253
+ time.sleep(update_interval)
254
+
255
+ # Check if the stop button has been pressed
256
+ if not st.session_state.running:
257
+ break
258
+
259
+ # Display final state if simulation has been stopped
260
+ if not st.session_state.running and 'fig' in locals():
261
+ chart_placeholder.plotly_chart(fig, use_container_width=True)