File size: 4,157 Bytes
cab60db 3ffebe8 599d710 3ffebe8 ce76895 cab60db 599d710 396e0c2 3ffebe8 ce76895 3ffebe8 cab60db 599d710 3ffebe8 cab60db 3ffebe8 f1e60b9 3ffebe8 f1e60b9 3ffebe8 396e0c2 f1e60b9 3ffebe8 f1e60b9 3ffebe8 599d710 ce76895 3ffebe8 599d710 cab60db 396e0c2 30998ff 396e0c2 cab60db ce76895 599d710 ce76895 599d710 3ffebe8 ce76895 0bc0cd3 f1e60b9 599d710 396e0c2 599d710 30998ff 599d710 30998ff 599d710 30998ff 599d710 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
import random
from scipy.stats import entropy as scipy_entropy
import time
st.set_page_config(layout="wide")
# --- НАСТРОЙКИ ---
seqlen = 60
steps = 120
min_run, max_run = 1, 2
ANGLE_MAP = {'A': 60.0, 'C': 180.0, 'G': -60.0, 'T': -180.0, 'N': 0.0}
bases = ['A', 'C', 'G', 'T']
# --- БИО-ФУНКЦИИ ---
def find_local_min_runs(profile, min_run=1, max_run=2):
result = []
N = len(profile)
i = 0
while i < N:
run_val = profile[i]
run_length = 1
while i + run_length < N and profile[i + run_length] == run_val:
run_length += 1
if min_run <= run_length <= max_run:
result.append((i, i + run_length - 1, run_val))
i += run_length
return result
def bio_mutate(seq):
r = random.random()
if r < 0.70:
idx = random.randint(0, len(seq)-1)
orig = seq[idx]
prob = random.random()
if orig in 'AG':
newbase = 'C' if prob < 0.65 else random.choice(['T', 'C'])
elif orig in 'CT':
newbase = 'G' if prob < 0.65 else random.choice(['A', 'G'])
else:
newbase = random.choice([b for b in bases if b != orig])
seq = seq[:idx] + newbase + seq[idx+1:]
elif r < 0.80:
idx = random.randint(0, len(seq)-1)
ins = ''.join(random.choices(bases, k=random.randint(1, 3)))
seq = seq[:idx] + ins + seq[idx:]
if len(seq) > seqlen:
seq = seq[:seqlen]
elif r < 0.90:
if len(seq) > 4:
idx = random.randint(0, len(seq)-2)
dell = random.randint(1, min(3, len(seq)-idx))
seq = seq[:idx] + seq[idx+dell:]
else:
if len(seq) > 10:
start = random.randint(0, len(seq)-6)
end = start + random.randint(3,6)
subseq = seq[start:end][::-1]
seq = seq[:start] + subseq + seq[end:]
while len(seq) < seqlen:
seq += random.choice(bases)
return seq[:seqlen]
def compute_autocorr(profile):
profile = profile - np.mean(profile)
result = np.correlate(profile, profile, mode='full')
result = result[result.size // 2:]
norm = np.max(result) if np.max(result) != 0 else 1
return result[:10]/norm
def compute_entropy(profile):
vals, counts = np.unique(profile, return_counts=True)
p = counts / counts.sum()
return scipy_entropy(p, base=2)
# --- ИНТЕРФЕЙС ---
st.title("🧬 Эфир: Живой поток мутаций ДНК")
st.markdown("Анализ биологических свойств последовательности в реальном времени.")
plot_placeholder = st.empty()
if st.button("▶️ Начать эфир"):
seq = ''.join(random.choices(bases, k=seqlen))
stat_bist_counts = []
stat_entropy = []
stat_autocorr = []
for step in range(steps):
if step != 0:
seq = bio_mutate(seq)
torsion_profile = np.array([ANGLE_MAP.get(nt, 0.0) for nt in seq])
runs = find_local_min_runs(torsion_profile, min_run, max_run)
stat_bist_counts.append(len(runs))
ent = compute_entropy(torsion_profile)
stat_entropy.append(ent)
acorr = compute_autocorr(torsion_profile)
fig, axs = plt.subplots(3, 1, figsize=(10, 8))
plt.subplots_adjust(hspace=0.45)
axs[0].plot(torsion_profile, color='royalblue')
for start, end, val in runs:
axs[0].axvspan(start, end, color="red", alpha=0.3)
axs[0].set_ylim(-200, 200)
axs[0].set_title(f"Шаг {step}: {seq}")
axs[0].set_ylabel("Торсионный угол")
axs[1].plot(stat_bist_counts, '-o', color='crimson', markersize=4)
axs[1].set_ylabel("Биомашины")
axs[1].set_title("Количество машин")
axs[2].bar(np.arange(6), acorr[:6], color='teal')
axs[2].set_title(f"Автокорреляция / Энтропия: {ent:.2f}")
axs[2].set_xlabel("Лаг")
plot_placeholder.pyplot(fig)
plt.close(fig)
time.sleep(0.3)
|