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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -43
app.py CHANGED
@@ -4,16 +4,31 @@ 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
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()
@@ -27,24 +42,24 @@ def bio_mutate(seq):
27
  newbase = 'G' if prob < 0.65 else random.choice(['A', 'G'])
28
  else:
29
  newbase = random.choice([b for b in bases if b != orig])
30
- seq = seq[:idx] + newbase + seq[idx+1:]
31
  elif r < 0.80:
32
  idx = random.randint(0, len(seq)-1)
33
  ins = ''.join(random.choices(bases, k=random.randint(1, 3)))
34
- seq = seq[:idx] + ins + seq[idx:]
35
  if len(seq) > seqlen:
36
  seq = seq[:seqlen]
37
  elif r < 0.90:
38
  if len(seq) > 4:
39
  idx = random.randint(0, len(seq)-2)
40
  dell = random.randint(1, min(3, len(seq)-idx))
41
- seq = seq[:idx] + seq[idx+dell:]
42
  else:
43
  if len(seq) > 10:
44
  start = random.randint(0, len(seq)-6)
45
  end = start + random.randint(3,6)
46
  subseq = seq[start:end][::-1]
47
- seq = seq[:start] + subseq + seq[end:]
48
  while len(seq) < seqlen:
49
  seq += random.choice(bases)
50
  return seq[:seqlen]
@@ -61,25 +76,6 @@ def compute_entropy(profile):
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("🔴 Живой эфир мутаций ДНК")
85
  start = st.button("▶️ Старт эфира")
@@ -88,8 +84,7 @@ stop = st.checkbox("⏹️ Остановить")
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
 
@@ -99,28 +94,24 @@ if start:
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)
 
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
+ def find_local_min_runs(profile, min_run=1, max_run=2):
20
+ result = []
21
+ N = len(profile)
22
+ i = 0
23
+ while i < N:
24
+ run_val = profile[i]
25
+ run_length = 1
26
+ while i + run_length < N and profile[i + run_length] == run_val:
27
+ run_length += 1
28
+ if min_run <= run_length <= max_run:
29
+ result.append((i, i + run_length - 1, run_val))
30
+ i += run_length
31
+ return result
32
 
33
  def bio_mutate(seq):
34
  r = random.random()
 
42
  newbase = 'G' if prob < 0.65 else random.choice(['A', 'G'])
43
  else:
44
  newbase = random.choice([b for b in bases if b != orig])
45
+ seq = ''.join(seq[:idx]) + newbase + ''.join(seq[idx+1:])
46
  elif r < 0.80:
47
  idx = random.randint(0, len(seq)-1)
48
  ins = ''.join(random.choices(bases, k=random.randint(1, 3)))
49
+ seq = ''.join(seq[:idx]) + ins + ''.join(seq[idx:])
50
  if len(seq) > seqlen:
51
  seq = seq[:seqlen]
52
  elif r < 0.90:
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 = ''.join(seq[:idx]) + ''.join(seq[idx+dell:])
57
  else:
58
  if len(seq) > 10:
59
  start = random.randint(0, len(seq)-6)
60
  end = start + random.randint(3,6)
61
  subseq = seq[start:end][::-1]
62
+ seq = ''.join(seq[:start]) + ''.join(subseq) + ''.join(seq[end:])
63
  while len(seq) < seqlen:
64
  seq += random.choice(bases)
65
  return seq[:seqlen]
 
76
  p = counts / counts.sum()
77
  return scipy_entropy(p, base=2)
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  # --- UI ---
80
  st.title("🔴 Живой эфир мутаций ДНК")
81
  start = st.button("▶️ Старт эфира")
 
84
  plot_placeholder = st.empty()
85
 
86
  if start:
87
+ seq = ''.join(random.choices(bases, k=seqlen))
 
88
  stat_bist_counts = []
89
  stat_entropy = []
90
 
 
94
  st.warning("⏹️ Эфир остановлен пользователем.")
95
  break
96
 
97
+ if step != 0:
98
+ seq = bio_mutate(seq)
99
+
100
+ torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
101
+ runs = find_local_min_runs(torsion_profile, min_run, max_run)
102
+ stat_bist_counts.append(len(runs))
103
+ ent = compute_entropy(torsion_profile)
 
 
 
 
 
 
104
  stat_entropy.append(ent)
105
+ acorr = compute_autocorr(torsion_profile)
106
 
107
  fig, axs = plt.subplots(3, 1, figsize=(10, 8))
108
  plt.subplots_adjust(hspace=0.45)
109
 
110
+ axs[0].plot(torsion_profile, color='royalblue')
111
+ for start_, end_, val in runs:
112
+ axs[0].axvspan(start_, end_, color="red", alpha=0.3)
113
  axs[0].set_ylim(-200, 200)
114
+ axs[0].set_title(f"Шаг {step}: {seq}")
115
  axs[0].set_ylabel("Торсионный угол")
116
 
117
  axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=4)