Dmtlant commited on
Commit
154fef1
·
verified ·
1 Parent(s): 6c5a763

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -58
app.py CHANGED
@@ -4,35 +4,17 @@ import matplotlib.pyplot as plt
4
  import random
5
  from scipy.stats import entropy as scipy_entropy
6
  import time
7
- import imageio
8
- from datetime import datetime
9
-
10
- st.set_page_config(layout="wide")
11
 
12
  # --- ПАРАМЕТРЫ ---
13
  seqlen = 60
14
  min_run, max_run = 1, 2
15
  ANGLE_MAP = {'A': 60.0, 'C': 180.0, 'G': -60.0, 'T': -180.0, 'N': 0.0}
16
  bases = ['A', 'C', 'G', 'T']
 
 
17
 
18
  # --- ФУНКЦИИ ---
19
 
20
- # Функция для нахождения локальных минимумов (например, биомашин)
21
- def find_local_min_runs(profile, min_run=1, max_run=2):
22
- result = []
23
- N = len(profile)
24
- i = 0
25
- while i < N:
26
- run_val = profile[i]
27
- run_length = 1
28
- while i + run_length < N and profile[i + run_length] == run_val:
29
- run_length += 1
30
- if min_run <= run_length <= max_run:
31
- result.append((i, i + run_length - 1, run_val))
32
- i += run_length
33
- return result
34
-
35
- # Функция для мутации последовательности
36
  def bio_mutate(seq):
37
  r = random.random()
38
  if r < 0.70:
@@ -67,7 +49,6 @@ def bio_mutate(seq):
67
  seq += random.choice(bases)
68
  return seq[:seqlen]
69
 
70
- # Функция для вычисления автокорреляции
71
  def compute_autocorr(profile):
72
  profile = profile - np.mean(profile)
73
  result = np.correlate(profile, profile, mode='full')
@@ -75,27 +56,29 @@ def compute_autocorr(profile):
75
  norm = np.max(result) if np.max(result) != 0 else 1
76
  return result[:10]/norm
77
 
78
- # Функция для вычисления энтропии
79
  def compute_entropy(profile):
80
  vals, counts = np.unique(profile, return_counts=True)
81
  p = counts / counts.sum()
82
  return scipy_entropy(p, base=2)
83
 
84
- # Функция для вычисления фрактальной размерности (корреляционной размерности)
85
- def correlation_dimension(data, max_radius=20, min_points=5):
86
- N = len(data)
87
- dimensions = []
88
- for radius in range(1, max_radius):
89
- count = 0
90
- for i in range(N):
91
- for j in range(i + 1, N):
92
- if np.abs(data[i] - data[j]) < radius:
93
- count += 1
94
- if count > min_points and radius > 1:
95
- dimension = np.log(count) / np.log(radius)
96
- dimensions.append(dimension)
 
 
97
 
98
- return np.mean(dimensions) if dimensions else 0
 
99
 
100
  # --- UI ---
101
  st.title("🔴 Живой эфир мутаций ДНК")
@@ -105,10 +88,10 @@ stop = st.checkbox("⏹️ Остановить")
105
  plot_placeholder = st.empty()
106
 
107
  if start:
108
- seq = ''.join(random.choices(bases, k=seqlen))
 
109
  stat_bist_counts = []
110
  stat_entropy = []
111
- stat_fractal = []
112
 
113
  step = 0
114
  while True:
@@ -116,28 +99,28 @@ if start:
116
  st.warning("⏹️ Эфир остановлен пользователем.")
117
  break
118
 
119
- if step != 0:
120
- seq = bio_mutate(seq)
 
 
 
 
 
 
 
121
 
122
- torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
123
- runs = find_local_min_runs(torsion_profile, min_run, max_run)
124
- stat_bist_counts.append(len(runs))
125
- ent = compute_entropy(torsion_profile)
126
  stat_entropy.append(ent)
127
-
128
- acorr = compute_autocorr(torsion_profile)
129
-
130
- fractal_dimension = correlation_dimension(torsion_profile)
131
- stat_fractal.append(fractal_dimension)
132
 
133
- fig, axs = plt.subplots(4, 1, figsize=(10, 10))
134
  plt.subplots_adjust(hspace=0.45)
135
 
136
- axs[0].plot(torsion_profile, color='royalblue')
137
- for start_, end_, val in runs:
138
- axs[0].axvspan(start_, end_, color="red", alpha=0.3)
139
  axs[0].set_ylim(-200, 200)
140
- axs[0].set_title(f"Шаг {step}: {seq}")
141
  axs[0].set_ylabel("Торсионный угол")
142
 
143
  axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=4)
@@ -148,10 +131,6 @@ if start:
148
  axs[2].set_title(f"Автокорреляция / Энтропия: {ent:.2f}")
149
  axs[2].set_xlabel("Лаг")
150
 
151
- axs[3].plot(stat_fractal, '-o', color='green', markersize=4)
152
- axs[3].set_title("Фрактальная размерность")
153
- axs[3].set_ylabel("Размерность")
154
-
155
  plot_placeholder.pyplot(fig)
156
  plt.close(fig)
157
 
 
4
  import random
5
  from scipy.stats import entropy as scipy_entropy
6
  import time
 
 
 
 
7
 
8
  # --- ПАРАМЕТРЫ ---
9
  seqlen = 60
10
  min_run, max_run = 1, 2
11
  ANGLE_MAP = {'A': 60.0, 'C': 180.0, 'G': -60.0, 'T': -180.0, 'N': 0.0}
12
  bases = ['A', 'C', 'G', 'T']
13
+ population_size = 10 # размер популяции "организмов"
14
+ survival_rate = 0.5 # процент выживших для следующего поколения
15
 
16
  # --- ФУНКЦИИ ---
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  def bio_mutate(seq):
19
  r = random.random()
20
  if r < 0.70:
 
49
  seq += random.choice(bases)
50
  return seq[:seqlen]
51
 
 
52
  def compute_autocorr(profile):
53
  profile = profile - np.mean(profile)
54
  result = np.correlate(profile, profile, mode='full')
 
56
  norm = np.max(result) if np.max(result) != 0 else 1
57
  return result[:10]/norm
58
 
 
59
  def compute_entropy(profile):
60
  vals, counts = np.unique(profile, return_counts=True)
61
  p = counts / counts.sum()
62
  return scipy_entropy(p, base=2)
63
 
64
+ def genetic_algorithm(population):
65
+ """Эволюционный алгоритм для отбора и мутации."""
66
+ # Отбор лучших организмов
67
+ population.sort(key=lambda x: x[1]) # сортируем по фитнесу (энтропия)
68
+ survivors = population[:int(population_size * survival_rate)]
69
+
70
+ # Кроссовер: создаем новых организмов на основе выживших
71
+ offspring = []
72
+ for i in range(len(survivors) // 2):
73
+ parent1, parent2 = survivors[i], survivors[-i-1]
74
+ crossover_point = random.randint(0, seqlen)
75
+ child1 = parent1[0][:crossover_point] + parent2[0][crossover_point:]
76
+ child2 = parent2[0][:crossover_point] + parent1[0][crossover_point:]
77
+ offspring.append((bio_mutate(child1), 0))
78
+ offspring.append((bio_mutate(child2), 0))
79
 
80
+ # Возвращаем новое поколение
81
+ return survivors + offspring
82
 
83
  # --- UI ---
84
  st.title("🔴 Живой эфир мутаций ДНК")
 
88
  plot_placeholder = st.empty()
89
 
90
  if start:
91
+ # Начальная популяция
92
+ population = [(random.choices(bases, k=seqlen), 0) for _ in range(population_size)]
93
  stat_bist_counts = []
94
  stat_entropy = []
 
95
 
96
  step = 0
97
  while True:
 
99
  st.warning("⏹️ Эфир остановлен пользователем.")
100
  break
101
 
102
+ # Мутация и оценка каждого организма в популяции
103
+ for i in range(population_size):
104
+ seq, _ = population[i]
105
+ torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
106
+ ent = compute_entropy(torsion_profile)
107
+ population[i] = (seq, ent)
108
+
109
+ # Применяем эволюционный алгоритм
110
+ population = genetic_algorithm(population)
111
 
112
+ # Статистика для отображения
113
+ stat_bist_counts.append(len(population))
114
+ ent = np.mean([ind[1] for ind in population]) # средняя энтропия
 
115
  stat_entropy.append(ent)
116
+ acorr = compute_autocorr(np.array([ANGLE_MAP.get(nt, 0.0) for nt in population[0][0]]))
 
 
 
 
117
 
118
+ fig, axs = plt.subplots(3, 1, figsize=(10, 8))
119
  plt.subplots_adjust(hspace=0.45)
120
 
121
+ axs[0].plot([ANGLE_MAP.get(nt, 0.0) for nt in population[0][0]], color='royalblue')
 
 
122
  axs[0].set_ylim(-200, 200)
123
+ axs[0].set_title(f"Шаг {step}: {population[0][0]}")
124
  axs[0].set_ylabel("Торсионный угол")
125
 
126
  axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=4)
 
131
  axs[2].set_title(f"Автокорреляция / Энтропия: {ent:.2f}")
132
  axs[2].set_xlabel("Лаг")
133
 
 
 
 
 
134
  plot_placeholder.pyplot(fig)
135
  plt.close(fig)
136