Dmtlant commited on
Commit
396e0c2
·
verified ·
1 Parent(s): c64746a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -40
app.py CHANGED
@@ -4,13 +4,13 @@ import matplotlib.pyplot as plt
4
  import random
5
  from scipy.stats import entropy as scipy_entropy
6
 
7
- # Настройки
8
  seqlen = 60
 
9
  min_run, max_run = 1, 2
10
  ANGLE_MAP = {'A': 60.0, 'C': 180.0, 'G': -60.0, 'T': -180.0, 'N': 0.0}
11
  bases = ['A', 'C', 'G', 'T']
12
 
13
- # --- Логика ---
14
  def find_local_min_runs(profile, min_run=1, max_run=2):
15
  result = []
16
  N = len(profile)
@@ -42,7 +42,8 @@ def bio_mutate(seq):
42
  idx = random.randint(0, len(seq)-1)
43
  ins = ''.join(random.choices(bases, k=random.randint(1, 3)))
44
  seq = seq[:idx] + ins + seq[idx:]
45
- seq = seq[:seqlen]
 
46
  elif r < 0.90:
47
  if len(seq) > 4:
48
  idx = random.randint(0, len(seq)-2)
@@ -52,61 +53,79 @@ def bio_mutate(seq):
52
  if len(seq) > 10:
53
  start = random.randint(0, len(seq)-6)
54
  end = start + random.randint(3,6)
55
- subseq = seq[start:end][::-1]
56
- seq = seq[:start] + subseq + seq[end:]
 
57
  while len(seq) < seqlen:
58
  seq += random.choice(bases)
59
  if len(seq) > seqlen:
60
  seq = seq[:seqlen]
61
  return seq
62
 
63
- def compute_autocorr(profile):
64
- profile = profile - np.mean(profile)
65
- result = np.correlate(profile, profile, mode='full')
66
- result = result[result.size // 2:]
67
- norm = np.max(result) if np.max(result)!=0 else 1
68
- return result[:10]/norm
69
-
70
  def compute_entropy(profile):
71
  vals, counts = np.unique(profile, return_counts=True)
72
  p = counts / counts.sum()
73
  return scipy_entropy(p, base=2)
74
 
75
- # --- Streamlit UI ---
76
- st.title("🧬 Эволюция ДНК-подобной цепи с мутациями")
77
- steps = st.slider("Число шагов симуляции", 1, 200, 60)
 
 
 
78
 
79
- if st.button("▶️ Запустить симуляцию"):
80
  seq = ''.join(random.choices(bases, k=seqlen))
81
  stat_bist_counts = []
82
  stat_entropy = []
83
  stat_autocorr = []
 
84
 
85
- fig, axs = plt.subplots(3, 1, figsize=(10, 8))
86
- plt.subplots_adjust(hspace=0.45)
 
87
 
88
- for i in range(steps):
89
  torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
90
  runs = find_local_min_runs(torsion_profile, min_run, max_run)
91
  stat_bist_counts.append(len(runs))
92
- stat_entropy.append(compute_entropy(torsion_profile))
93
- stat_autocorr.append(compute_autocorr(torsion_profile))
94
- seq = bio_mutate(seq)
95
-
96
- # Отрисовка последнего состояния
97
- axs[0].plot(torsion_profile, color='royalblue', label="Торсионный угол")
98
- for start, end, val in runs:
99
- axs[0].axvspan(start, end, color="red", alpha=0.3)
100
- axs[0].plot(range(start, end+1), torsion_profile[start:end+1], 'ro', markersize=5)
101
- axs[0].set_ylim(-200, 200)
102
- axs[0].set_title(f"Шаг {steps}: {seq}\nЧисло машин: {len(runs)}, энтропия: {stat_entropy[-1]:.2f}")
103
- axs[0].legend()
104
-
105
- axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=4)
106
- axs[1].set_title("Динамика: число 'биомашин'")
107
-
108
- axs[2].bar(np.arange(6), stat_autocorr[-1][:6], color='teal', alpha=0.7)
109
- axs[2].set_title("Автокорреляция и энтропия")
110
- axs[2].text(0.7, 0.7, f"Энтропия: {stat_entropy[-1]:.2f}", transform=axs[2].transAxes)
111
-
112
- st.pyplot(fig)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  import random
5
  from scipy.stats import entropy as scipy_entropy
6
 
7
+ # --- НАСТРОЙКИ ---
8
  seqlen = 60
9
+ steps = 100
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
 
 
14
  def find_local_min_runs(profile, min_run=1, max_run=2):
15
  result = []
16
  N = len(profile)
 
42
  idx = random.randint(0, len(seq)-1)
43
  ins = ''.join(random.choices(bases, k=random.randint(1, 3)))
44
  seq = seq[:idx] + ins + seq[idx:]
45
+ if len(seq) > seqlen:
46
+ seq = seq[:seqlen]
47
  elif r < 0.90:
48
  if len(seq) > 4:
49
  idx = random.randint(0, len(seq)-2)
 
53
  if len(seq) > 10:
54
  start = random.randint(0, len(seq)-6)
55
  end = start + random.randint(3,6)
56
+ subseq = seq[start:end]
57
+ seq = seq[:start] + subseq[::-1] + seq[end:]
58
+
59
  while len(seq) < seqlen:
60
  seq += random.choice(bases)
61
  if len(seq) > seqlen:
62
  seq = seq[:seqlen]
63
  return seq
64
 
 
 
 
 
 
 
 
65
  def compute_entropy(profile):
66
  vals, counts = np.unique(profile, return_counts=True)
67
  p = counts / counts.sum()
68
  return scipy_entropy(p, base=2)
69
 
70
+ def compute_autocorr(profile):
71
+ profile = profile - np.mean(profile)
72
+ result = np.correlate(profile, profile, mode='full')
73
+ result = result[result.size // 2:]
74
+ norm = np.max(result) if np.max(result) != 0 else 1
75
+ return result[:10]/norm
76
 
77
+ def simulate_and_plot(steps):
78
  seq = ''.join(random.choices(bases, k=seqlen))
79
  stat_bist_counts = []
80
  stat_entropy = []
81
  stat_autocorr = []
82
+ figs = []
83
 
84
+ for step in range(steps):
85
+ if step > 0:
86
+ seq = bio_mutate(seq)
87
 
 
88
  torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
89
  runs = find_local_min_runs(torsion_profile, min_run, max_run)
90
  stat_bist_counts.append(len(runs))
91
+ ent = compute_entropy(torsion_profile)
92
+ stat_entropy.append(ent)
93
+ acorr = compute_autocorr(torsion_profile)
94
+ stat_autocorr.append(acorr)
95
+
96
+ fig, axs = plt.subplots(3, 1, figsize=(8, 8))
97
+ plt.subplots_adjust(hspace=0.6)
98
+
99
+ # Торсионный профиль
100
+ axs[0].plot(torsion_profile, color='royalblue', label="Торсионный угол")
101
+ for start, end, val in runs:
102
+ axs[0].axvspan(start, end, color="red", alpha=0.3)
103
+ axs[0].plot(range(start, end+1), torsion_profile[start:end+1], 'ro', markersize=4)
104
+ axs[0].set_ylim(-200, 200)
105
+ axs[0].set_title(f"Шаг {step}: {seq}\nМашин: {len(runs)}, энтропия: {ent:.2f}")
106
+ axs[0].legend()
107
+
108
+ # Динамика количества машин
109
+ axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=3)
110
+ axs[1].set_ylim(0, max(10, max(stat_bist_counts)+1))
111
+ axs[1].set_title("Динамика: число 'биомашин'")
112
+
113
+ # Автокорреляция
114
+ axs[2].bar(np.arange(6), acorr[:6], color='teal', alpha=0.7)
115
+ axs[2].set_title("Автокорреляция и энтропия")
116
+ axs[2].text(0.7, 0.7, f"Энтропия: {ent:.2f}", transform=axs[2].transAxes)
117
+
118
+ figs.append(fig)
119
+
120
+ return figs
121
+
122
+ # --- Streamlit UI ---
123
+ st.set_page_config(layout="wide")
124
+ st.title("🧬 Эволюция ДНК: визуализация торсионного профиля, мутаций и структур")
125
+
126
+ steps = st.slider("Число шагов мутации", 10, 150, 50)
127
+ if st.button("▶ Запустить симуляцию"):
128
+ st.info("Генерируется...")
129
+ figures = simulate_and_plot(steps)
130
+ for fig in figures:
131
+ st.pyplot(fig)