Dmtlant commited on
Commit
774b580
·
verified ·
1 Parent(s): 019ae71

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +57 -67
app.py CHANGED
@@ -4,7 +4,6 @@ import matplotlib.pyplot as plt
4
  import random
5
  from scipy.stats import entropy as scipy_entropy
6
  import time
7
- import seaborn as sns
8
 
9
  # --- НАСТРОЙКИ ---
10
  seqlen = 60
@@ -29,7 +28,9 @@ def find_local_min_runs(profile, min_run=1, max_run=2):
29
 
30
  def bio_mutate(seq):
31
  r = random.random()
 
32
  if r < 0.70: # Точечная мутация
 
33
  idx = random.randint(0, len(seq)-1)
34
  orig = seq[idx]
35
  prob = random.random()
@@ -41,17 +42,20 @@ def bio_mutate(seq):
41
  newbase = random.choice([b for b in bases if b != orig])
42
  seq = seq[:idx] + newbase + seq[idx+1:]
43
  elif r < 0.80: # Инсерция короткого блока
 
44
  idx = random.randint(0, len(seq)-1)
45
  ins = ''.join(random.choices(bases, k=random.randint(1, 3)))
46
  seq = seq[:idx] + ins + seq[idx:]
47
  if len(seq) > seqlen:
48
  seq = seq[:seqlen]
49
  elif r < 0.90: # Делеция
 
50
  if len(seq) > 4:
51
  idx = random.randint(0, len(seq)-2)
52
  dell = random.randint(1, min(3, len(seq)-idx))
53
  seq = seq[:idx] + seq[idx+dell:]
54
  else: # Блочная перестановка (инверсия)
 
55
  if len(seq) > 10:
56
  start = random.randint(0, len(seq)-6)
57
  end = start + random.randint(3,6)
@@ -62,7 +66,7 @@ def bio_mutate(seq):
62
  seq += random.choice(bases)
63
  if len(seq) > seqlen:
64
  seq = seq[:seqlen]
65
- return seq
66
 
67
  def compute_autocorr(profile):
68
  profile = profile - np.mean(profile)
@@ -80,68 +84,12 @@ def compute_entropy(profile):
80
  st.title("🧬 Эволюция ДНК-подобной последовательности")
81
  st.markdown("Модель визуализирует мутации и анализирует структуру последовательности во времени.")
82
 
83
- # Функции для улучшения визуализации
84
-
85
- def plot_density(runs, ax, steps):
86
- machine_starts = [start for start, _, _ in runs]
87
- machine_ends = [end for _, end, _ in runs]
88
- timeline = np.zeros(steps)
89
-
90
- for start, end, _ in runs:
91
- timeline[start:end+1] = 1
92
-
93
- sns.lineplot(x=np.arange(steps), y=timeline, ax=ax, color='darkgreen')
94
- ax.set_title("Плотность биомашин по шагам")
95
- ax.set_xlabel("Шаг")
96
- ax.set_ylabel("Плотность биомашин")
97
-
98
- def plot_heatmap(runs, ax, steps):
99
- heatmap_matrix = np.zeros((steps, len(runs)))
100
-
101
- for idx, (start, end, _) in enumerate(runs):
102
- heatmap_matrix[start:end+1, idx] = 1
103
-
104
- sns.heatmap(heatmap_matrix, ax=ax, cmap="YlGnBu", cbar=True)
105
- ax.set_title("Тепловая карта: Распределение биомашин по времени")
106
- ax.set_xlabel("Номер биомашины")
107
- ax.set_ylabel("Шаг")
108
-
109
- def update_visualization(step, seq, runs, torsion_profile, stat_bist_counts, acorr, steps, lags_shown, ent):
110
- fig, axs = plt.subplots(5, 1, figsize=(10, 12))
111
- plt.subplots_adjust(hspace=0.45)
112
-
113
- axs[0].cla()
114
- axs[1].cla()
115
- axs[2].cla()
116
- axs[3].cla()
117
- axs[4].cla()
118
-
119
- axs[0].plot(torsion_profile, color='royalblue', label="Торсионный угол")
120
- for start, end, val in runs:
121
- axs[0].axvspan(start, end, color="red", alpha=0.3)
122
- axs[0].plot(range(start, end+1), torsion_profile[start:end+1], 'ro', markersize=5)
123
- axs[0].set_ylim(-200, 200)
124
- axs[0].set_xlabel("Позиция")
125
- axs[0].set_ylabel("Торсионный угол (град.)")
126
- axs[0].set_title(f"Шаг {step}: {seq}\nЧисло машин: {len(runs)}, энтропия: {ent:.2f}")
127
- axs[0].legend()
128
-
129
- plot_density(runs, axs[3], steps)
130
- plot_heatmap(runs, axs[4], steps)
131
-
132
- axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=4)
133
- axs[1].set_xlabel("Шаг")
134
- axs[1].set_ylabel("Число машин")
135
- axs[1].set_ylim(0, max(10, max(stat_bist_counts)+1))
136
- axs[1].set_title("Динамика: число 'биомашин'")
137
-
138
- axs[2].bar(np.arange(lags_shown), acorr[:lags_shown], color='teal', alpha=0.7)
139
- axs[2].set_xlabel("Лаг")
140
- axs[2].set_ylabel("Автокорреляция")
141
- axs[2].set_title("Автокорреляция углового профиля (структурность) и энтропия")
142
- axs[2].text(0.70, 0.70, f"Энтропия: {ent:.2f}", transform=axs[2].transAxes)
143
-
144
- plot_placeholder.pyplot(fig)
145
 
146
  # Кнопка запуска симуляции
147
  if st.button("▶️ Запустить симуляцию"):
@@ -149,12 +97,14 @@ if st.button("▶️ Запустить симуляцию"):
149
  stat_bist_counts = []
150
  stat_entropy = []
151
  stat_autocorr = []
 
152
 
153
  plot_placeholder = st.empty()
154
 
155
  for step in range(steps):
156
  if step != 0:
157
- seq = bio_mutate(seq)
 
158
  torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
159
  runs = find_local_min_runs(torsion_profile, min_run, max_run)
160
  stat_bist_counts.append(len(runs))
@@ -162,6 +112,46 @@ if st.button("▶️ Запустить симуляцию"):
162
  stat_entropy.append(ent)
163
  acorr = compute_autocorr(torsion_profile)
164
 
165
- # Обновление визуализаций
166
- update_visualization(step, seq, runs, torsion_profile, stat_bist_counts, acorr, steps, 6, ent)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  time.sleep(0.5)
 
4
  import random
5
  from scipy.stats import entropy as scipy_entropy
6
  import time
 
7
 
8
  # --- НАСТРОЙКИ ---
9
  seqlen = 60
 
28
 
29
  def bio_mutate(seq):
30
  r = random.random()
31
+ mutation_type = None
32
  if r < 0.70: # Точечная мутация
33
+ mutation_type = 'Point Mutation'
34
  idx = random.randint(0, len(seq)-1)
35
  orig = seq[idx]
36
  prob = random.random()
 
42
  newbase = random.choice([b for b in bases if b != orig])
43
  seq = seq[:idx] + newbase + seq[idx+1:]
44
  elif r < 0.80: # Инсерция короткого блока
45
+ mutation_type = 'Insertion'
46
  idx = random.randint(0, len(seq)-1)
47
  ins = ''.join(random.choices(bases, k=random.randint(1, 3)))
48
  seq = seq[:idx] + ins + seq[idx:]
49
  if len(seq) > seqlen:
50
  seq = seq[:seqlen]
51
  elif r < 0.90: # Делеция
52
+ mutation_type = 'Deletion'
53
  if len(seq) > 4:
54
  idx = random.randint(0, len(seq)-2)
55
  dell = random.randint(1, min(3, len(seq)-idx))
56
  seq = seq[:idx] + seq[idx+dell:]
57
  else: # Блочная перестановка (инверсия)
58
+ mutation_type = 'Block Inversion'
59
  if len(seq) > 10:
60
  start = random.randint(0, len(seq)-6)
61
  end = start + random.randint(3,6)
 
66
  seq += random.choice(bases)
67
  if len(seq) > seqlen:
68
  seq = seq[:seqlen]
69
+ return seq, mutation_type
70
 
71
  def compute_autocorr(profile):
72
  profile = profile - np.mean(profile)
 
84
  st.title("🧬 Эволюция ДНК-подобной последовательности")
85
  st.markdown("Модель визуализирует мутации и анализирует структуру последовательности во времени.")
86
 
87
+ # Настройка параметров симуляции
88
+ st.sidebar.header("Настройки симуляции")
89
+ steps = st.sidebar.slider("Шаги симуляции", min_value=50, max_value=300, value=120)
90
+ seqlen = st.sidebar.slider("Длина последовательности", min_value=40, max_value=100, value=60)
91
+ min_run = st.sidebar.slider("Мин. длина биомашины", min_value=1, max_value=5, value=1)
92
+ max_run = st.sidebar.slider("Макс. длина биомашины", min_value=2, max_value=10, value=2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
  # Кнопка запуска симуляции
95
  if st.button("▶️ Запустить симуляцию"):
 
97
  stat_bist_counts = []
98
  stat_entropy = []
99
  stat_autocorr = []
100
+ mutation_types = []
101
 
102
  plot_placeholder = st.empty()
103
 
104
  for step in range(steps):
105
  if step != 0:
106
+ seq, mutation_type = bio_mutate(seq)
107
+ mutation_types.append(mutation_type)
108
  torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
109
  runs = find_local_min_runs(torsion_profile, min_run, max_run)
110
  stat_bist_counts.append(len(runs))
 
112
  stat_entropy.append(ent)
113
  acorr = compute_autocorr(torsion_profile)
114
 
115
+ # Визуализация
116
+ fig, axs = plt.subplots(3, 1, figsize=(10, 8))
117
+ plt.subplots_adjust(hspace=0.45)
118
+ lags_shown = 6
119
+
120
+ axs[0].cla()
121
+ axs[1].cla()
122
+ axs[2].cla()
123
+
124
+ axs[0].plot(torsion_profile, color='royalblue', label="Торсионный угол")
125
+ for start, end, val in runs:
126
+ axs[0].axvspan(start, end, color="red", alpha=0.3)
127
+ axs[0].plot(range(start, end+1), torsion_profile[start:end+1], 'ro', markersize=5)
128
+ axs[0].set_ylim(-200, 200)
129
+ axs[0].set_xlabel("Позиция")
130
+ axs[0].set_ylabel("Торсионный угол (град.)")
131
+ axs[0].set_title(f"Шаг {step}: {seq}\nЧисло машин: {len(runs)}, энтропия: {ent:.2f}")
132
+ axs[0].legend()
133
+
134
+ axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=4)
135
+ axs[1].set_xlabel("Шаг")
136
+ axs[1].set_ylabel("Число машин")
137
+ axs[1].set_ylim(0, max(10, max(stat_bist_counts)+1))
138
+ axs[1].set_title("Динамика: число 'биомашин'")
139
+
140
+ axs[2].bar(np.arange(lags_shown), acorr[:lags_shown], color='teal', alpha=0.7)
141
+ axs[2].set_xlabel("Лаг")
142
+ axs[2].set_ylabel("Автокорреляция")
143
+ axs[2].set_title("Автокорреляция углового профиля (структурность) и энтропия")
144
+ axs[2].text(0.70, 0.70, f"Энтропия: {ent:.2f}", transform=axs[2].transAxes)
145
+
146
+ # Тепловая карта мутаций
147
+ fig2, ax2 = plt.subplots(figsize=(10, 2))
148
+ ax2.imshow([mutation_types], aspect='auto', cmap='coolwarm', interpolation='nearest')
149
+ ax2.set_yticks([])
150
+ ax2.set_xticks(range(steps))
151
+ ax2.set_xticklabels(range(steps), rotation=90)
152
+ ax2.set_xlabel('Шаги симуляции')
153
+ ax2.set_title('Тепловая карта типов мутаций')
154
+
155
+ plot_placeholder.pyplot(fig)
156
+ plot_placeholder.pyplot(fig2)
157
  time.sleep(0.5)