Dmtlant commited on
Commit
70a14b2
·
verified ·
1 Parent(s): 774b580

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -57
app.py CHANGED
@@ -4,6 +4,7 @@ import matplotlib.pyplot as plt
4
  import random
5
  from scipy.stats import entropy as scipy_entropy
6
  import time
 
7
 
8
  # --- НАСТРОЙКИ ---
9
  seqlen = 60
@@ -28,9 +29,7 @@ def find_local_min_runs(profile, min_run=1, max_run=2):
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,20 +41,17 @@ def bio_mutate(seq):
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,7 +62,7 @@ def bio_mutate(seq):
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,12 +80,68 @@ def compute_entropy(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,14 +149,12 @@ 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,46 +162,6 @@ if st.button("▶️ Запустить симуляцию"):
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)
 
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
 
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
  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
  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
  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
  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
  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)