File size: 7,393 Bytes
a8cc94d
23bd555
9633bd9
bcfb38f
9633bd9
9686272
23bd555
 
9633bd9
23bd555
 
 
 
 
 
9633bd9
23bd555
 
9633bd9
23bd555
 
 
 
 
 
 
 
56aed2d
23bd555
9686272
 
23bd555
 
 
9686272
 
da47dd8
9686272
 
 
 
 
23bd555
9686272
56aed2d
23bd555
 
9686272
 
 
23bd555
9686272
 
 
23bd555
 
 
9686272
bcfb38f
 
 
 
 
9686272
 
 
 
 
 
bcfb38f
 
 
 
56aed2d
bcfb38f
23bd555
 
9686272
 
 
 
 
bcfb38f
 
 
 
 
 
9686272
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bcfb38f
 
23bd555
 
9686272
23bd555
9686272
 
23bd555
 
56aed2d
 
9686272
56aed2d
23bd555
 
c87ff7e
9686272
 
bcfb38f
c87ff7e
 
 
23bd555
 
 
56aed2d
23bd555
9686272
 
 
23bd555
9686272
23bd555
9686272
23bd555
 
 
 
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import streamlit as st
from brian2 import *
import numpy as np
import plotly.graph_objects as go

def run_simulation(num_neurons=12, sim_time=100*ms):
    # Установка времени симуляции и временного шага
    defaultclock.dt = 0.1*ms

    # Определение уравнений для нейронов
    eqs = '''
    dv/dt = (I - v)/tau : 1 (unless refractory)
    I : 1
    tau : second
    '''

    # Создание группы нейронов
    G = NeuronGroup(num_neurons, eqs, threshold='v>1', reset='v = 0', refractory=5*ms, method='euler')

    # Начальные условия
    G.I = np.linspace(1.5, 2.0, num_neurons)  # Разные токи для разных сегментов
    G.tau = 10*ms

    # Создание переменной для записи результатов
    M = StateMonitor(G, 'v', record=True)

    # Запуск симуляции
    run(sim_time)

    # Моделирование механики червя
    # Упрощенная модель: каждый сегмент движется в зависимости от активности нейронов

    # Параметры червя
    segment_length = 0.5  # Длина каждого сегмента
    num_segments = num_neurons
    worm_length = segment_length * num_segments

    # Начальные позиции сегментов (случайные)
    num_frames = len(M.t)
    positions = np.zeros((num_frames, num_segments, 2))
    initial_positions = np.random.rand(num_segments, 2) * 10  # Случайные начальные позиции в пространстве 10x10
    positions[0, :, :] = initial_positions

    # Обновление позиций сегментов на основе активности нейронов
    for frame in range(1, num_frames):
        for i in range(num_segments):
            if i == 0:
                # Головной сегмент движется случайным образом
                positions[frame, i, 0] = positions[frame-1, i, 0] + (np.random.rand() - 0.5) * 0.5
                positions[frame, i, 1] = positions[frame-1, i, 1] + (np.random.rand() - 0.5) * 0.5
            else:
                # Остальные сегменты следуют за предыдущими
                positions[frame, i, 0] = positions[frame-1, i-1, 0] + segment_length
                positions[frame, i, 1] = positions[frame-1, i-1, 1] + (M.v[i][frame] - 1) * 0.1

    return positions, M.t

def create_plotly_animation(positions, times):
    num_frames, num_segments, _ = positions.shape

    # Создание фигуры Plotly
    fig = go.Figure(
        layout=go.Layout(
            xaxis=dict(range=[-10, 20], autorange=False),
            yaxis=dict(range=[-10, 20], autorange=False),
            title="Движение червя",
            showlegend=False,
            width=800,
            height=600
        )
    )

    # Добавление кадров
    frames = []
    for frame in range(num_frames):
        x = positions[frame, :, 0]
        y = positions[frame, :, 1]
        frames.append(go.Frame(data=[go.Scatter(x=x, y=y, mode='lines+markers',
                                               marker=dict(size=10, color='blue'),
                                               line=dict(width=2, color='blue'))],
                               name=f'frame{frame}',
                               layout=go.Layout(title_text=f'Время: {times[frame]:.1f} ms')))

    fig.frames = frames

    # Добавление начального состояния
    initial_x = positions[0, :, 0]
    initial_y = positions[0, :, 1]
    fig.add_trace(go.Scatter(x=initial_x, y=initial_y, mode='lines+markers',
                             marker=dict(size=10, color='blue'),
                             line=dict(width=2, color='blue')))

    # Настройка анимации
    fig.update_layout(
        updatemenus=[
            dict(
                type="buttons",
                buttons=[
                    dict(label="▶️ Запустить",
                         method="animate",
                         args=[None, {"frame": {"duration": 100, "redraw": True},
                                      "fromcurrent": True, "transition": {"duration": 0}}]),
                    dict(label="⏹️ Остановить",
                         method="animate",
                         args=[[None], {"frame": {"duration": 0, "redraw": False},
                                        "mode": "immediate",
                                        "transition": {"duration": 0}}])
                ],
                showactive=False,
                x=0,
                y=1.05
            )
        ]
    )

    return fig

def main():
    st.title("Симуляция движения червя с использованием Streamlit и Brian2")
    st.write("""
    Это веб-приложение выполняет симуляцию нейронной активности и соответствующего движения червя.
    Используется **Plotly** для отображения интерактивной анимации.
    """)

    st.sidebar.header("Параметры Симуляции")
    num_neurons = st.sidebar.slider('Количество сегментов червя', min_value=5, max_value=20, value=12)
    sim_time_ms = st.sidebar.slider('Время симуляции (мс)', min_value=50, max_value=500, value=100, step=10)

    if st.button("Запустить симуляцию"):
        with st.spinner('Выполнение симуляции и создание анимации...'):
            try:
                positions, times = run_simulation(num_neurons=num_neurons, sim_time=sim_time_ms*ms)
                fig = create_plotly_animation(positions, times)
                st.plotly_chart(fig, use_container_width=True)
                st.success('Симуляция завершена!')
            except Exception as e:
                st.error(f"Произошла ошибка: {e}")

    st.write("""
    ### Описание
    - **Количество сегментов червя**: устанавливается пользователем (по умолчанию 12)
    - **Длина каждого сегмента**: 0.5 единиц
    - **Время симуляции**: устанавливается пользователем (по умолчанию 100 мс)
    - **Модель нейронов**: Простая модель с параметрами I и tau, влияющими на потенциал v.
    
    ### Как это работает
    1. **Симуляция нейронов**: Создается группа нейронов с разными токами и временем релаксации.
    2. **Механика червя**: Каждому сегменту соответствует нейрон. Активность нейронов влияет на движение сегментов.
    3. **Анимация**: Полученные позиции сегментов визуализируются в интерактивной анимации движения червя.
    """)

if __name__ == "__main__":
    main()