Sephfox commited on
Commit
d4c9b56
·
verified ·
1 Parent(s): 1140353

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +112 -45
app.py CHANGED
@@ -230,13 +230,22 @@ def setup_figure(env):
230
 
231
  return fig
232
 
 
 
 
 
 
 
 
 
233
  # Streamlit app
234
- st.title("Advanced Cell Evolution Simulation")
235
 
236
- initial_cells = st.slider("Initial number of cells", 10, 500, 200)
237
- update_interval = st.slider("Update interval (seconds)", 0.01, 1.0, 0.05) # Increased speed
 
 
238
 
239
- # Effect options
240
  st.sidebar.header("Environmental Effects")
241
  radiation = st.sidebar.checkbox("Radiation")
242
  predation = st.sidebar.checkbox("Predation")
@@ -248,62 +257,120 @@ effects = {
248
  "symbiosis": symbiosis
249
  }
250
 
251
- # Create placeholders for the chart and stop button
 
 
 
 
 
 
 
 
 
 
 
 
 
252
  chart_placeholder = st.empty()
253
- stop_button_placeholder = st.empty()
254
 
255
  # Initialize session state
256
  if 'running' not in st.session_state:
257
  st.session_state.running = False
 
 
 
 
 
 
258
 
259
  def toggle_simulation():
260
  st.session_state.running = not st.session_state.running
 
 
 
 
 
 
261
 
262
  start_stop_button = st.button("Start/Stop Simulation", on_click=toggle_simulation)
263
 
264
- if st.session_state.running:
265
- env = Environment(100, 100, effects)
266
- for _ in range(initial_cells):
267
- cell = Cell(random.uniform(0, env.width), random.uniform(0, env.height))
268
- env.add_cell(cell)
269
-
270
- fig = setup_figure(env)
271
-
272
- while st.session_state.running:
273
- for _ in range(4): # Update 4 times per frame to increase simulation speed
274
- env.update()
275
-
276
- with fig.batch_update():
277
- cell_data, population_history, colors = env.get_visualization_data()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
278
 
279
- # Update cell distribution
280
- for i, (cell_type, data) in enumerate(cell_data.items()):
281
- fig.data[i].x = data["x"]
282
- fig.data[i].y = data["y"]
283
- fig.data[i].marker.size = data["size"]
284
 
285
- # Update total population
286
- total_population = [sum(counts) for counts in zip(*population_history.values())]
287
- fig.data[len(cell_data)].y = total_population
288
 
289
- # Update population by cell type
290
- for i, (cell_type, counts) in enumerate(population_history.items()):
291
- fig.data[len(cell_data) + 1 + i].y = counts
292
 
293
- # Update organelle distribution
294
- organelle_counts = {"nucleus": 0, "mitochondria": 0, "chloroplast": 0, "endoplasmic_reticulum": 0, "golgi_apparatus": 0}
295
- for cell in env.cells:
296
- for organelle in cell.organelles:
297
- organelle_counts[organelle] += 1
298
- fig.data[-1].y = list(organelle_counts.values())
299
-
300
- chart_placeholder.plotly_chart(fig, use_container_width=True)
301
  time.sleep(update_interval)
302
 
303
- # Check if the stop button has been pressed
304
- if not st.session_state.running:
305
- break
 
 
 
306
 
307
- # Display final state if simulation has been stopped
308
- if not st.session_state.running and 'fig' in locals():
309
- chart_placeholder.plotly_chart(fig, use_container_width=True)
 
230
 
231
  return fig
232
 
233
+ def format_number(num):
234
+ if num >= 1_000_000:
235
+ return f"{num/1_000_000:.1f}M"
236
+ elif num >= 1_000:
237
+ return f"{num/1_000:.1f}K"
238
+ else:
239
+ return str(num)
240
+
241
  # Streamlit app
242
+ st.title("Continuous Cell Evolution Simulation")
243
 
244
+ # Sidebar for controls and live statistics
245
+ st.sidebar.header("Simulation Controls")
246
+ initial_cells = st.sidebar.slider("Initial number of cells", 10, 500, 200)
247
+ update_interval = st.sidebar.slider("Update interval (seconds)", 0.01, 1.0, 0.05)
248
 
 
249
  st.sidebar.header("Environmental Effects")
250
  radiation = st.sidebar.checkbox("Radiation")
251
  predation = st.sidebar.checkbox("Predation")
 
257
  "symbiosis": symbiosis
258
  }
259
 
260
+ # Live statistics placeholders
261
+ st.sidebar.header("Live Statistics")
262
+ total_cells_text = st.sidebar.empty()
263
+ cell_type_breakdown = st.sidebar.empty()
264
+ dominant_type_text = st.sidebar.empty()
265
+ avg_energy_text = st.sidebar.empty()
266
+ total_merges_text = st.sidebar.empty()
267
+
268
+ # Event log
269
+ st.sidebar.header("Event Log")
270
+ event_log = deque(maxlen=10) # Keep the last 10 events
271
+ event_log_text = st.sidebar.empty()
272
+
273
+ # Create placeholders for the chart
274
  chart_placeholder = st.empty()
 
275
 
276
  # Initialize session state
277
  if 'running' not in st.session_state:
278
  st.session_state.running = False
279
+ if 'total_merges' not in st.session_state:
280
+ st.session_state.total_merges = 0
281
+ if 'env' not in st.session_state:
282
+ st.session_state.env = None
283
+ if 'fig' not in st.session_state:
284
+ st.session_state.fig = None
285
 
286
  def toggle_simulation():
287
  st.session_state.running = not st.session_state.running
288
+ if st.session_state.running and st.session_state.env is None:
289
+ st.session_state.env = Environment(100, 100, effects)
290
+ for _ in range(initial_cells):
291
+ cell = Cell(random.uniform(0, st.session_state.env.width), random.uniform(0, st.session_state.env.height))
292
+ st.session_state.env.add_cell(cell)
293
+ st.session_state.fig = setup_figure(st.session_state.env)
294
 
295
  start_stop_button = st.button("Start/Stop Simulation", on_click=toggle_simulation)
296
 
297
+ def run_simulation():
298
+ while True:
299
+ if st.session_state.running:
300
+ for _ in range(4): # Update 4 times per frame to increase simulation speed
301
+ initial_cell_count = len(st.session_state.env.cells)
302
+ st.session_state.env.update()
303
+ final_cell_count = len(st.session_state.env.cells)
304
+
305
+ # Check for merges
306
+ if final_cell_count < initial_cell_count:
307
+ merges = initial_cell_count - final_cell_count
308
+ st.session_state.total_merges += merges
309
+ event_log.appendleft(f"Time {st.session_state.env.time}: {merges} cell merge(s) occurred!")
310
+
311
+ # Check for new cell types
312
+ for cell in st.session_state.env.cells:
313
+ if cell.cell_type not in st.session_state.env.population_history:
314
+ event_log.appendleft(f"Time {st.session_state.env.time}: New cell type '{cell.cell_type}' emerged!")
315
+
316
+ time.sleep(update_interval)
317
+
318
+ def update_chart():
319
+ while True:
320
+ if st.session_state.running and st.session_state.fig is not None:
321
+ with st.session_state.fig.batch_update():
322
+ cell_data, population_history, colors = st.session_state.env.get_visualization_data()
323
+
324
+ # Update cell distribution
325
+ for i, (cell_type, data) in enumerate(cell_data.items()):
326
+ st.session_state.fig.data[i].x = data["x"]
327
+ st.session_state.fig.data[i].y = data["y"]
328
+ st.session_state.fig.data[i].marker.size = data["size"]
329
+
330
+ # Update total population
331
+ total_population = [sum(counts) for counts in zip(*population_history.values())]
332
+ st.session_state.fig.data[len(cell_data)].y = total_population
333
+
334
+ # Update population by cell type
335
+ for i, (cell_type, counts) in enumerate(population_history.items()):
336
+ st.session_state.fig.data[len(cell_data) + 1 + i].y = counts
337
+
338
+ # Update organelle distribution
339
+ organelle_counts = {"nucleus": 0, "mitochondria": 0, "chloroplast": 0, "endoplasmic_reticulum": 0, "golgi_apparatus": 0}
340
+ for cell in st.session_state.env.cells:
341
+ for organelle in cell.organelles:
342
+ organelle_counts[organelle] += 1
343
+ st.session_state.fig.data[-1].y = list(organelle_counts.values())
344
+
345
+ # Update live statistics
346
+ total_cells = len(st.session_state.env.cells)
347
+ total_cells_text.text(f"Total Cells: {format_number(total_cells)}")
348
+
349
+ cell_type_counts = {cell_type: len([c for c in st.session_state.env.cells if c.cell_type == cell_type]) for cell_type in st.session_state.env.population_history.keys()}
350
+ cell_type_breakdown.text("Cell Type Breakdown:\n" + "\n".join([f"{cell_type}: {format_number(count)}" for cell_type, count in cell_type_counts.items()]))
351
 
352
+ dominant_type = max(cell_type_counts, key=cell_type_counts.get)
353
+ dominant_type_text.text(f"Dominant Type: {dominant_type}")
 
 
 
354
 
355
+ avg_energy = sum(cell.energy for cell in st.session_state.env.cells) / total_cells if total_cells > 0 else 0
356
+ avg_energy_text.text(f"Avg Energy: {avg_energy:.2f}")
 
357
 
358
+ total_merges_text.text(f"Total Merges: {st.session_state.total_merges}")
 
 
359
 
360
+ # Update event log
361
+ event_log_text.text("Recent Events:\n" + "\n".join(event_log))
362
+
363
+ chart_placeholder.plotly_chart(st.session_state.fig, use_container_width=True)
364
+
 
 
 
365
  time.sleep(update_interval)
366
 
367
+ # Start the simulation and chart update threads
368
+ simulation_thread = threading.Thread(target=run_simulation)
369
+ chart_thread = threading.Thread(target=update_chart)
370
+
371
+ simulation_thread.start()
372
+ chart_thread.start()
373
 
374
+ # Keep the main thread alive
375
+ while True:
376
+ time.sleep(1)