Sephfox commited on
Commit
16eb022
1 Parent(s): 55aad04

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +77 -45
app.py CHANGED
@@ -7,7 +7,12 @@ import time
7
 
8
  class Organelle:
9
  def __init__(self, type):
10
- self.type = type # e.g., "nucleus", "mitochondria", "chloroplast"
 
 
 
 
 
11
 
12
  class Cell:
13
  def __init__(self, x, y, cell_type="prokaryote"):
@@ -16,21 +21,23 @@ class Cell:
16
  self.energy = 100
17
  self.cell_type = cell_type
18
  self.organelles = []
 
19
  self.size = 1
20
- self.color = "blue"
21
  self.division_threshold = 150
22
 
23
- if cell_type == "prokaryote":
24
- self.color = "lightblue"
25
- elif cell_type == "early_eukaryote":
 
26
  self.organelles.append(Organelle("nucleus"))
27
  self.color = "green"
28
  self.size = 2
29
- elif cell_type == "advanced_eukaryote":
30
  self.organelles.extend([Organelle("nucleus"), Organelle("mitochondria")])
31
  self.color = "red"
32
  self.size = 3
33
- elif cell_type == "plant_like":
34
  self.organelles.extend([Organelle("nucleus"), Organelle("mitochondria"), Organelle("chloroplast")])
35
  self.color = "darkgreen"
36
  self.size = 4
@@ -43,13 +50,15 @@ class Cell:
43
  self.energy -= 0.5 * self.size
44
 
45
  def feed(self, environment):
 
46
  if "chloroplast" in [org.type for org in self.organelles]:
47
- # Photosynthesis
48
- self.energy += environment.light_level * 2
49
- else:
50
- # Consume environmental nutrients
51
- self.energy += environment.grid[int(self.y)][int(self.x)] * 0.1
52
- environment.grid[int(self.y)][int(self.x)] *= 0.9
 
53
 
54
  def can_divide(self):
55
  return self.energy > self.division_threshold
@@ -57,35 +66,57 @@ class Cell:
57
  def divide(self):
58
  if self.can_divide():
59
  self.energy /= 2
60
- return Cell(self.x, self.y, self.cell_type)
 
 
 
61
  return None
62
 
63
  def can_fuse(self, other):
64
- return (self.cell_type == "prokaryote" and other.cell_type == "prokaryote" and
65
- random.random() < 0.001) # 0.1% chance of fusion
66
 
67
  def fuse(self, other):
 
 
 
 
 
 
68
  new_cell = Cell(
69
  (self.x + other.x) / 2,
70
  (self.y + other.y) / 2,
71
- "early_eukaryote"
72
  )
73
  new_cell.energy = self.energy + other.energy
 
 
 
74
  return new_cell
75
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  class Environment:
77
  def __init__(self, width, height):
78
  self.width = width
79
  self.height = height
80
- self.grid = np.random.rand(height, width) * 10 # Nutrient distribution
81
- self.light_level = 5 # Ambient light level
82
  self.cells = []
83
  self.time = 0
84
  self.population_history = {
85
- "prokaryote": [],
86
- "early_eukaryote": [],
87
- "advanced_eukaryote": [],
88
- "plant_like": []
89
  }
90
 
91
  def add_cell(self, cell):
@@ -93,10 +124,8 @@ class Environment:
93
 
94
  def update(self):
95
  self.time += 1
96
-
97
- # Update environment
98
  self.grid += np.random.rand(self.height, self.width) * 0.1
99
- self.light_level = 5 + np.sin(self.time / 100) * 2 # Fluctuating light levels
100
 
101
  new_cells = []
102
  cells_to_remove = []
@@ -124,23 +153,24 @@ class Environment:
124
  self.cells.extend(new_cells)
125
  self.cells = [cell for cell in self.cells if cell not in cells_to_remove]
126
 
127
- # Introduce mutations
128
  for cell in self.cells:
129
  if random.random() < 0.0001: # 0.01% chance of mutation
130
  if cell.cell_type == "early_eukaryote":
131
  cell.cell_type = "advanced_eukaryote"
132
- cell.organelles.append(Organelle("mitochondria"))
133
- cell.color = "red"
134
- cell.size = 3
135
  elif cell.cell_type == "advanced_eukaryote" and random.random() < 0.5:
136
  cell.cell_type = "plant_like"
137
- cell.organelles.append(Organelle("chloroplast"))
138
- cell.color = "darkgreen"
139
- cell.size = 4
 
140
 
141
  # Record population counts
142
  for cell_type in self.population_history.keys():
143
- count = len([cell for cell in self.cells if cell.cell_type == cell_type])
 
 
 
144
  self.population_history[cell_type].append(count)
145
 
146
  def get_visualization_data(self):
@@ -148,13 +178,15 @@ class Environment:
148
  "prokaryote": {"x": [], "y": [], "size": [], "color": "lightblue"},
149
  "early_eukaryote": {"x": [], "y": [], "size": [], "color": "green"},
150
  "advanced_eukaryote": {"x": [], "y": [], "size": [], "color": "red"},
151
- "plant_like": {"x": [], "y": [], "size": [], "color": "darkgreen"}
 
152
  }
153
 
154
  for cell in self.cells:
155
- cell_data[cell.cell_type]["x"].append(cell.x)
156
- cell_data[cell.cell_type]["y"].append(cell.y)
157
- cell_data[cell.cell_type]["size"].append(cell.size * 3)
 
158
 
159
  return cell_data, self.population_history
160
 
@@ -178,16 +210,16 @@ def setup_figure(env):
178
  fig.update_xaxes(title_text="Time", row=1, col=2)
179
  fig.update_yaxes(title_text="Population", row=1, col=2)
180
 
181
- fig.update_layout(height=600, width=1200, title_text="Cell Evolution Simulation")
182
 
183
  return fig
184
 
185
  # Streamlit app
186
- st.title("Cell Evolution Simulation")
187
 
188
- num_steps = st.slider("Number of simulation steps", 100, 1000, 500)
189
- initial_cells = st.slider("Initial number of cells", 10, 100, 50)
190
- update_interval = st.slider("Update interval (milliseconds)", 100, 1000, 200)
191
 
192
  if st.button("Run Simulation"):
193
  env = Environment(100, 100)
@@ -214,9 +246,9 @@ if st.button("Run Simulation"):
214
  fig.data[i].marker.size = data["size"]
215
 
216
  for i, (cell_type, counts) in enumerate(population_history.items()):
217
- fig.data[i+4].y = counts # +4 because we have 4 cell types in the first subplot
218
 
219
- fig.layout.title.text = f"Cell Evolution Simulation (Time: {env.time})"
220
 
221
  # Update the chart
222
  chart.plotly_chart(fig, use_container_width=True)
 
7
 
8
  class Organelle:
9
  def __init__(self, type):
10
+ self.type = type
11
+
12
+ class Modification:
13
+ def __init__(self, name, effect):
14
+ self.name = name
15
+ self.effect = effect
16
 
17
  class Cell:
18
  def __init__(self, x, y, cell_type="prokaryote"):
 
21
  self.energy = 100
22
  self.cell_type = cell_type
23
  self.organelles = []
24
+ self.modifications = []
25
  self.size = 1
26
+ self.color = "lightblue"
27
  self.division_threshold = 150
28
 
29
+ self.update_properties()
30
+
31
+ def update_properties(self):
32
+ if self.cell_type == "early_eukaryote":
33
  self.organelles.append(Organelle("nucleus"))
34
  self.color = "green"
35
  self.size = 2
36
+ elif self.cell_type == "advanced_eukaryote":
37
  self.organelles.extend([Organelle("nucleus"), Organelle("mitochondria")])
38
  self.color = "red"
39
  self.size = 3
40
+ elif self.cell_type == "plant_like":
41
  self.organelles.extend([Organelle("nucleus"), Organelle("mitochondria"), Organelle("chloroplast")])
42
  self.color = "darkgreen"
43
  self.size = 4
 
50
  self.energy -= 0.5 * self.size
51
 
52
  def feed(self, environment):
53
+ base_energy = environment.grid[int(self.y)][int(self.x)] * 0.1
54
  if "chloroplast" in [org.type for org in self.organelles]:
55
+ base_energy += environment.light_level * 2
56
+
57
+ for mod in self.modifications:
58
+ base_energy *= mod.effect
59
+
60
+ self.energy += base_energy
61
+ environment.grid[int(self.y)][int(self.x)] *= 0.9
62
 
63
  def can_divide(self):
64
  return self.energy > self.division_threshold
 
66
  def divide(self):
67
  if self.can_divide():
68
  self.energy /= 2
69
+ new_cell = Cell(self.x, self.y, self.cell_type)
70
+ new_cell.organelles = self.organelles.copy()
71
+ new_cell.modifications = self.modifications.copy()
72
+ return new_cell
73
  return None
74
 
75
  def can_fuse(self, other):
76
+ return (self.cell_type == other.cell_type and
77
+ random.random() < 0.005) # 0.5% chance of fusion
78
 
79
  def fuse(self, other):
80
+ new_cell_type = self.cell_type
81
+ if self.cell_type == "prokaryote":
82
+ new_cell_type = "early_eukaryote"
83
+ elif self.cell_type == "early_eukaryote":
84
+ new_cell_type = "advanced_eukaryote"
85
+
86
  new_cell = Cell(
87
  (self.x + other.x) / 2,
88
  (self.y + other.y) / 2,
89
+ new_cell_type
90
  )
91
  new_cell.energy = self.energy + other.energy
92
+ new_cell.organelles = list(set(self.organelles + other.organelles))
93
+ new_cell.modifications = list(set(self.modifications + other.modifications))
94
+ new_cell.update_properties()
95
  return new_cell
96
 
97
+ def acquire_modification(self):
98
+ possible_mods = [
99
+ Modification("Enhanced metabolism", 1.2),
100
+ Modification("Thick cell wall", 0.8),
101
+ Modification("Efficient energy storage", 1.1),
102
+ Modification("Rapid division", 0.9)
103
+ ]
104
+ new_mod = random.choice(possible_mods)
105
+ if new_mod not in self.modifications:
106
+ self.modifications.append(new_mod)
107
+ self.color = "purple" # Visual indicator of modification
108
+
109
  class Environment:
110
  def __init__(self, width, height):
111
  self.width = width
112
  self.height = height
113
+ self.grid = np.random.rand(height, width) * 10
114
+ self.light_level = 5
115
  self.cells = []
116
  self.time = 0
117
  self.population_history = {
118
+ "prokaryote": [], "early_eukaryote": [],
119
+ "advanced_eukaryote": [], "plant_like": [], "modified": []
 
 
120
  }
121
 
122
  def add_cell(self, cell):
 
124
 
125
  def update(self):
126
  self.time += 1
 
 
127
  self.grid += np.random.rand(self.height, self.width) * 0.1
128
+ self.light_level = 5 + np.sin(self.time / 100) * 2
129
 
130
  new_cells = []
131
  cells_to_remove = []
 
153
  self.cells.extend(new_cells)
154
  self.cells = [cell for cell in self.cells if cell not in cells_to_remove]
155
 
156
+ # Introduce mutations and modifications
157
  for cell in self.cells:
158
  if random.random() < 0.0001: # 0.01% chance of mutation
159
  if cell.cell_type == "early_eukaryote":
160
  cell.cell_type = "advanced_eukaryote"
 
 
 
161
  elif cell.cell_type == "advanced_eukaryote" and random.random() < 0.5:
162
  cell.cell_type = "plant_like"
163
+ cell.update_properties()
164
+
165
+ if random.random() < 0.0005: # 0.05% chance of acquiring a modification
166
+ cell.acquire_modification()
167
 
168
  # Record population counts
169
  for cell_type in self.population_history.keys():
170
+ if cell_type != "modified":
171
+ count = len([cell for cell in self.cells if cell.cell_type == cell_type and not cell.modifications])
172
+ else:
173
+ count = len([cell for cell in self.cells if cell.modifications])
174
  self.population_history[cell_type].append(count)
175
 
176
  def get_visualization_data(self):
 
178
  "prokaryote": {"x": [], "y": [], "size": [], "color": "lightblue"},
179
  "early_eukaryote": {"x": [], "y": [], "size": [], "color": "green"},
180
  "advanced_eukaryote": {"x": [], "y": [], "size": [], "color": "red"},
181
+ "plant_like": {"x": [], "y": [], "size": [], "color": "darkgreen"},
182
+ "modified": {"x": [], "y": [], "size": [], "color": "purple"}
183
  }
184
 
185
  for cell in self.cells:
186
+ cell_type = "modified" if cell.modifications else cell.cell_type
187
+ cell_data[cell_type]["x"].append(cell.x)
188
+ cell_data[cell_type]["y"].append(cell.y)
189
+ cell_data[cell_type]["size"].append(cell.size * 3)
190
 
191
  return cell_data, self.population_history
192
 
 
210
  fig.update_xaxes(title_text="Time", row=1, col=2)
211
  fig.update_yaxes(title_text="Population", row=1, col=2)
212
 
213
+ fig.update_layout(height=600, width=1200, title_text="Advanced Cell Evolution Simulation")
214
 
215
  return fig
216
 
217
  # Streamlit app
218
+ st.title("Advanced Cell Evolution Simulation")
219
 
220
+ num_steps = st.slider("Number of simulation steps", 100, 2000, 1000)
221
+ initial_cells = st.slider("Initial number of cells", 10, 200, 100)
222
+ update_interval = st.slider("Update interval (milliseconds)", 50, 500, 100)
223
 
224
  if st.button("Run Simulation"):
225
  env = Environment(100, 100)
 
246
  fig.data[i].marker.size = data["size"]
247
 
248
  for i, (cell_type, counts) in enumerate(population_history.items()):
249
+ fig.data[i+5].y = counts # +5 because we have 5 cell types in the first subplot
250
 
251
+ fig.layout.title.text = f"Advanced Cell Evolution Simulation (Time: {env.time})"
252
 
253
  # Update the chart
254
  chart.plotly_chart(fig, use_container_width=True)