引言
STA的定义
图 1 STA的定义[1]
图1形象地展示了STA分析的基本思路:最上一行的连续曲线为外界的刺激,如外界声音响度的变化,曲线下方不同颜色的短竖线代表单个神经元在声音播放期间先后爆发的8次spike(横轴为时间轴),如听皮层神经元对外界声音刺激的反应。将所有的spike移至时间轴上的同一时刻(长虚线),观察8次spike前的声音响度(不同颜色的曲线),再对其求取平均(最下方黑色线),就得到了诱发这个神经元的平均刺激,即Spike-triggered Average。
绘制STA图
弱电鱼(Eigenmannia),利用体内的电器官产生振荡的电场来感知环境,同时,它们也借助皮肤表面的电感受器感知周围物体对电场的干扰,从而识别物体的位置和特征。电感受器接收到的电场变化信号被传输到其大脑电感侧线叶(electrosensory lateral-line lobe),这是电鱼电感知系统的中枢结构。电感侧线叶的神经元对特定的电场变化模式敏感。STA能帮助我们了解神经元对电场变化的反应特性,从而揭示电鱼在复杂水下环境中的电感知能力[2]。
import numpy as np
import matplotlib.pyplot as plt
# Seed for reproducibility
np.random.seed(42)
# Parameters for synthetic data
sampling_rate = 1000 # in Hz
duration = 2 # in seconds
time = np.arange(0, duration, 1/sampling_rate) # time vector
首先生成一段模拟的外界电场变化。为保证每次生成的结果更加稳定,选取随机种子42;这里我们只分析一段2s时间跨度的数据;因为不分析具体的spike波形变化,所以采样率设置成1000Hz即可。
frequencies = [3, 7, 13] # multiple frequencies for more complexity
stimulus = sum(np.sin(2 * np.pi * f * time) for f in frequencies) # sum of sinusoids
noise = 0.3 * np.random.randn(len(time)) # increased noise level
stimulus += noise
stimulus *= 0.5 # scale down to match example range
基于傅立叶原理的基本思想,生成一段模拟的电位振荡,再在其中添加适度的噪音,使其和真实数据更接近。
# Plot stimulus potential immediately after generating the data
plt.figure(figsize=(6, 3))
plt.plot(time, stimulus, 'k')
plt.title('Stimulus Potential')
plt.ylabel('Potential (mV)')
plt.xlabel('Time (s)')
plt.ylim(-2, 2)
plt.grid(True)
plt.show()
上述代码执行完后生成如上图所示的外界电位振荡曲线。
接下来再生成一段电感侧线叶的神经元的动作电位:
threshold = 0.6 # threshold for spike generation, modify for realistic firing
spike_probability = np.clip((stimulus - threshold), 0, None) # only positive values above threshold
spike_probability /= np.max(spike_probability) # normalize to max probability 1
spike_probability *= 0.4 # further scale down to make spikes even sparser
# Convert spike probability to a rate (spikes per second)
spike_rate = spike_probability * sampling_rate # rate in spikes per second
# Generate spike train using Poisson process
spikes = np.zeros(len(time))
for i in range(len(time)):
spikes[i] = np.random.poisson(spike_rate[i] / sampling_rate) # Poisson process with rate
结合外界的电场刺激和神经元放电的本来规律(泊松过程)生成一段spike序列。
# Plot spike train immediately after generating the data
plt.figure(figsize=(6, 3))
plt.vlines(time[spikes > 0], ymin=0, ymax=1, color='k') # Draw vertical lines for spikes
plt.title('Evoked Spike Train')
plt.xlabel('Time (s)')
plt.ylim(-0.1, 1.1) # Set limits to ensure consistent appearance of spikes
plt.yticks([]) # Remove y-axis ticks
plt.xticks(np.arange(0, duration + 0.5, 0.5)) # Show x-axis ticks at intervals of 0.5 seconds
plt.axhline(y=0, color='k', linestyle='--') # Add horizontal line at y=0
plt.grid(True, which='both', linestyle='--', linewidth=0.5) # Add gridlines for clarity
plt.show()
绘制spike序列的图像
现在,我们既有外界电场电位的数据,也有其诱发的神经元spike序列,紧接着,我们就可以分析二者间的STA关系了:
# Calculate spike-triggered average (STA)
window = int(0.3 * sampling_rate) # 300 ms window for STA
sta = np.zeros(window) # initialize STA for negative time only
# Find indices of spikes
spike_indices = np.where(spikes == 1)[0]
for idx in spike_indices:
if idx > window: # only consider past data, not future
sta += stimulus[idx-window:idx]
# Normalize STA
if len(spike_indices) > 0:
sta /= len(spike_indices)
sta_time = np.arange(-window, 0) / sampling_rate * 1000 # in ms, negative time only
注意,我们只计算spike发生前的外界刺激,而在spike序列的0-300ms内,我们未记录外界电场变化的数据,即0-300ms段spike序列的数据无效。
# Plot STA immediately after generating the data
plt.figure(figsize=(6, 4))
plt.plot(sta_time, sta * 1000, 'k')
plt.title('Spike-Triggered Average Stimulus')
plt.xlabel('Time (ms)')
plt.ylabel('C (mV)')
plt.grid(True)
plt.xlim(-300, 0) # negative time only
plt.show()
绘制STA图:
上图表明,在每次电鱼神经元spike发生前的200ms左右,都有一次外界电位振荡的低谷,而在spike发生前的50ms内,都会有一段外界电位振荡的快速上升。由此,该图能较好地说明该神经元的感受野特征。
上述外界刺激的变化只是一维的电位强度变化,当外界刺激为多维度的信息时(图5),则需要对刺激进行降维处理,如图5B所示,右图中的白色点为spike发生前的刺激组合,而黑色点表示平均刺激组合,在降维后的二维空间中二者可被区分开来。
除了STA,我们还可以进一步计算spike发生前刺激组合的协方差,即STC(Spike-triggered Covariance)。如图6所示,通过计算协方差矩阵的特征向量,我们可以定量描述spike发生前刺激组合的特征。图6B表明,椭圆短轴(minor axis)方向上的刺激变化对神经元放电的影响是 “抑制性”的,换句话说,如果刺激在短轴方向上有较大的分量,神经元放电的可能性则会降低。椭圆的长轴(major axis)与原始刺激的方差相匹配,表示在这些方向上的刺激变化对神经元的放电率没有显著影响。
借助STA计算放电率
重新定义研究场景下的问题:电鱼身边环境中出现了一段电位振荡,我们需要预测电鱼电感受神经元的放电规律。
量化这一过程最高效的方法就是建立模型,此处外界刺激即是模型的输入,神经元反应就是模型的输出,而STA就是决定输入到输出函数的关键元素。
首先生成新的电场振荡:
# Generate a new fluctuating stimulus potential with noise
frequencies2 = [2, 7, 10] # multiple frequencies for more complexity
stimulus2 = sum(np.sin(2 * np.pi * f * time) for f in frequencies) # sum of sinusoids
noise2 = 0.2 * np.random.randn(len(time)) # increased noise level
stimulus2 += noise
stimulus2 *= 0.5 # scale down to match example range
紧跟着,用前文中求得的STA曲线与电场振荡求取卷积[4],因为STA只有300ms,短于新生成的2000ms的外界刺激,故STA作为卷积核(kernel),而外界刺激,即新生成的电场振荡,作为卷积的信号(signal):
from scipy.stats import zscore
def compute_and_plot_firing_rate(stimulus, sta, time, mode, title):
# Perform convolution to estimate firing rate
predicted_firing_rate = np.convolve(stimulus, sta, mode)
# Normalize using Z-score
predicted_firing_rate = zscore(predicted_firing_rate)
# Ensure firing rate is positive
predicted_firing_rate = np.clip(predicted_firing_rate, 0, None)
# Adjust time vector if mode is 'valid'
if mode == 'valid':
valid_length = len(predicted_firing_rate)
time = time[(len(time) - valid_length) // 2: (len(time) + valid_length) // 2]
# Plot normalized predicted firing rate
plt.figure(figsize=(6, 4))
plt.plot(time, predicted_firing_rate, 'k')
plt.title(title)
plt.xlabel('Time (s)')
plt.ylabel('Firing Rate')
plt.grid(True)
plt.show()
compute_and_plot_firing_rate(stimulus2, sta, time, 'same', 'Predicted Firing Rate (Same Mode)')
compute_and_plot_firing_rate(stimulus, sta, time, 'valid', 'Predicted Firing Rate (Valid Mode)')
借助numpy内置的卷积函数,我们完成了STA和刺激的卷积,注意这里我们先后选用了两种卷积模式,same模式能使卷积结果和signal的长度一样;而在“valid”模式下,卷积结果的长度为signal长度减kernel长度后再加1,为此,我们需要调整横坐标time的长度,以匹配卷积结果。
图 8 “same”卷积预测的电感神经元放电频率
图 9 “valid”卷积预测的电感神经元放电频率
从更广义的角度看,“valid”和“same”卷积模式影响了结果的长度和对信号边界的处理。“valid”模式仅在输入信号的完全重叠区域计算卷积,因此结果短于输入,适用于需要准确计算重叠区域的场景,但会丢失边界信息。“same”模式则保证输出长度与输入相同,通过在signal边界添加零填充来计算卷积,使结果在信号边界处也有代表性。
下图较好地描述了两种卷积方法的异同:
结语
从“准确描述能引起神经元反应的外界刺激”这个核心问题出发,我们先后介绍了STA的概念和计算方法,又在其基础上,讨论了利用STA来预测神经元反应模式的方法。长期埋头于神经元反应的草蛇灰线后,或许我们可以转个身,将目光投回外界刺激,说不定就会有不一样的发现。
参考文献
[1]https://www.columbia.edu/cu/appliedneuroshp/Spring2018/Spring18SHPAppliedNeuroLec4.pdf
往期推荐
投 稿 方 式
关注我
|脑洞峰谷|
在体多通道电生理领域专家
关注我,下期见!