MNE-Python 第4天学习笔记:数据预处理(一)—— 滤波与重参考

一、为什么需要预处理?

1.1 原始数据中的"杂质"

脑电信号非常微弱(微伏级),容易被各种噪声污染:

python 复制代码
原始信号 = 大脑信号 + 工频干扰 + 眼动伪迹 + 肌肉伪迹 + ...
         ↑           ↑           ↑           ↑
      我们想要的    50Hz交流电   眨眼/眼动    咬牙/转头

1.2 今天要解决的问题

二、环境准备与数据加载

python 复制代码
# ========== 环境设置 ==========
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import mne
import numpy as np
import os
import warnings
warnings.filterwarnings('ignore')

# 中文字体设置
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei']
plt.rcParams['axes.unicode_minus'] = False

print("="*60)
print("MNE-Python 第4天:滤波与重参考")
print("="*60)

# ---------- 加载数据 ----------
sample_data_folder = mne.datasets.sample.data_path()
raw_fname = os.path.join(sample_data_folder, 'MEG', 'sample', 'sample_audvis_raw.fif')
raw = mne.io.read_raw_fif(raw_fname, preload=False)
print("✅ 原始数据加载完成")

# 提取 EEG 通道(使用第2天的方法)
raw_eeg = raw.copy().pick_types(eeg=True)
montage = mne.channels.make_standard_montage('standard_1020')
eeg_names = raw_eeg.ch_names
standard_names = montage.ch_names[:len(eeg_names)]
raw_eeg.rename_channels(dict(zip(eeg_names, standard_names)))
raw_eeg.set_montage(montage)
print(f"✅ EEG数据准备完成:{len(raw_eeg.ch_names)} 个通道")

# 加载数据到内存(预处理需要反复操作,预加载更快)
raw_eeg.load_data()
print("✅ 数据已加载到内存")

三、滤波前必看:查看原始频谱

3.1 为什么滤波前要看频谱?

python 复制代码
就像医生开药前要先做检查一样:
❌ 不要盲目滤波!
✅ 先看数据中有什么频率成分,再决定滤波参数

3.2 代码实现

python 复制代码
print("\n" + "="*60)
print("滤波前:查看原始频谱")
print("="*60)

print("正在绘制原始频谱...")

# plot_psd():绘制功率谱密度(Power Spectral Density)
# 
# 功率谱密度 = 各个频率上的信号能量
# 横轴:频率 (Hz)
# 纵轴:能量/功率 (dB 或 V²/Hz)
fig_before = raw_eeg.plot_psd(
    fmin=0.1,           # 显示的最低频率
    fmax=100,           # 显示的最高频率
    spatial_colors=True, # 每个通道用不同颜色
    average=False,       # 显示每个通道的曲线(不取平均)
    n_fft=8192          # FFT 窗口大小
)
plt.title('滤波前的功率谱密度 (PSD)', fontsize=14, fontweight='bold')
plt.show(block=True)

参数详解:

n_fft 的选择原理:

python 复制代码
频率分辨率 = 采样率 / n_fft

例如:采样率 600 Hz,n_fft=8192
频率分辨率 = 600/8192 ≈ 0.073 Hz

n_fft 越大 → 频率分辨率越细 → 能看到更窄的频率峰值
n_fft 越小 → 计算越快 → 但可能模糊掉窄带噪声

3.3 定量检查工频干扰

python 复制代码
# compute_psd():计算 PSD(不绘图,返回数据)
# 与 plot_psd() 的区别:
#   plot_psd():计算并绘图
#   compute_psd():只计算,返回数据用于后续分析

# get_data(return_freqs=True):获取 PSD 数据和频率数组
# return_freqs=True 同时返回频率值
psd_data, freqs = raw_eeg.compute_psd(
    fmin=0.1,   # 最小频率
    fmax=100    # 最大频率
).get_data(return_freqs=True)

# psd_data 的形状:(通道数, 频率点数)
# freqs 的形状:(频率点数,)
print(f"PSD 数据形状: {psd_data.shape}")
print(f"频率数组形状: {freqs.shape}")

# 检查 50Hz 附近是否有峰值
# np.argmin(np.abs(freqs - 50)) 的拆解:
#   freqs - 50:每个频率值减去 50
#   np.abs(...):取绝对值(距离 50Hz 有多远)
#   np.argmin(...):找到最小值的索引(最接近 50Hz 的位置)
idx_50 = np.argmin(np.abs(freqs - 50))
power_50 = np.mean(psd_data[:, idx_50])  # 所有通道在 50Hz 的平均功率
print(f"  50Hz 处平均功率: {power_50:.2e}")

# 检查 60Hz(美国标准)
idx_60 = np.argmin(np.abs(freqs - 60))
power_60 = np.mean(psd_data[:, idx_60])
print(f"  60Hz 处平均功率: {power_60:.2e}")

np.argmin(np.abs(freqs - 50)) 的详细拆解:

python 复制代码
# 假设 freqs = [0.1, 0.2, 0.3, ..., 49.8, 49.9, 50.0, 50.1, ...]

# 步骤1:freqs - 50
# = [-49.9, -49.8, -49.7, ..., -0.2, -0.1, 0.0, 0.1, ...]

# 步骤2:np.abs(freqs - 50) 
# = [49.9, 49.8, 49.7, ..., 0.2, 0.1, 0.0, 0.1, ...]
#                                   ↑ 距离 50Hz 最近

# 步骤3:np.argmin(np.abs(freqs - 50))
# 找到最小值的索引
# 如果 50.0 是第 500 个值,返回 500

四、陷波滤波:去除工频干扰

4.1 什么是工频干扰?

python 复制代码
电力系统使用交流电:
- 中国/欧洲:220V,50Hz(每秒正负变化 50 次)
- 美国:110V,60Hz

这个电磁场会通过以下方式进入脑电信号:
1. 电极导线像天线一样接收
2. 皮肤-电极界面的整流效应
3. 周围电器的电磁辐射

结果:在脑电信号的 50/60Hz 处出现一个"尖峰"

4.2 陷波滤波原理

python 复制代码
              │
    信号幅度   │    ┌─┐
              │    │ │      ← 50Hz 的尖峰(工频干扰)
              │  ╱   ╲
              │ ╱     ╲___  ← 正常脑电信号
              │╱
              └────────────────
                  频率 →

    陷波滤波器 = 在 50Hz 处"挖一个非常窄的坑"
    只去除 50Hz (±0.5Hz) 的信号
    其他频率完全保留

4.3 代码实现

python 复制代码
print("\n" + "="*60)
print("步骤1:陷波滤波 - 去除工频干扰")
print("="*60)

# 复制数据
# 为什么要复制?
#   保持 raw_eeg 不变,方便对比滤波前后的效果
raw_notch = raw_eeg.copy()

# 确定工频
# 这个数据集是美国实验室采集的,用 60Hz
# 如果是中国数据,改为 50
power_freq = 60  # Hz

# notch_filter():陷波滤波器
raw_notch.notch_filter(
    freqs=power_freq,        # 要去除的频率
    picks='eeg',             # 只对 EEG 通道操作
    fir_design='firwin',     # FIR 滤波器设计方法
    verbose=False            # 不打印详细信息
)
print(f"✅ 陷波滤波完成:去除了 {power_freq}Hz 工频干扰")

参数详解:

也可以去除谐波:

python 复制代码
# 为什么需要去除谐波?
# 工频干扰不仅在 50/60Hz 出现
# 还可能在倍频处出现:100/120Hz, 150/180Hz
# 这些叫"谐波"

# 去除 60Hz 及其 2次、3次谐波
raw_notch.notch_filter(
    freqs=[60, 120, 180],  # 基频 + 2倍频 + 3倍频
    picks='eeg',
    fir_design='firwin'
)

五、带通滤波:提取感兴趣频段

5.1 脑电频段划分

python 复制代码
# 脑电信号按频率可以分为几个经典频段:

print("""
脑电频段划分:
┌──────────┬──────────┬─────────────────────┐
│   频段   │ 频率范围 │      常见状态       │
├──────────┼──────────┼─────────────────────┤
│ Delta δ  │ 0.5-4 Hz │ 深度睡眠、婴儿       │
│ Theta θ  │ 4-8 Hz   │ 冥想、困倦、儿童     │
│ Alpha α  │ 8-13 Hz  │ 闭眼放松、清醒休息   │
│ Beta β   │ 13-30 Hz │ 专注、思考、焦虑     │
│ Gamma γ  │ 30-100Hz │ 高级认知、信息整合   │
└──────────┴──────────┴─────────────────────┘
""")

5.2 带通滤波原理

python 复制代码
              │
    信号幅度   │              ┌──────┐
              │              │通过区│  ← 保留 1-40Hz
              │    ╱         └──────┘
              │   ╱                     ╲
              │──╱  ← 高通1Hz     40Hz→ ╲──
              │╱                           ╲
              └────────────────────────────────
                  频率 →
    
带通滤波 = 高通滤波 + 低通滤波

高通滤波 (l_freq=1Hz):
    去除 1Hz 以下的信号
    作用:消除缓慢的基线漂移(出汗、电极移动导致)
    
低通滤波 (h_freq=40Hz):
    去除 40Hz 以上的信号
    作用:消除高频肌肉噪声和电磁干扰

5.3 代码实现

python 复制代码
print("\n" + "="*60)
print("步骤2:带通滤波 - 提取感兴趣频段")
print("="*60)

# 在陷波滤波的基础上继续
raw_filtered = raw_notch.copy()

# filter():带通滤波器
raw_filtered.filter(
    l_freq=1,               # 低截止频率(高通部分)
    h_freq=40,              # 高截止频率(低通部分)
    picks='eeg',            # 只对 EEG 通道操作
    method='fir',           # 使用 FIR 滤波器
    fir_design='firwin',    # FIR 窗函数设计法
    verbose=False           # 不打印详细信息
)
print("✅ 带通滤波完成:保留 1-40 Hz")

参数详解:

FIR vs IIR 滤波器:

5.4 不同频段的滤波示例

python 复制代码
print("\n不同频段滤波示例:")

# 从陷波后的数据出发,提取不同频段

# Alpha 波提取(8-13 Hz)
# 用途:闭眼放松分析、脑机接口
raw_alpha = raw_notch.copy().filter(
    l_freq=8, 
    h_freq=13, 
    picks='eeg', 
    verbose=False
)
print("  Alpha (8-13 Hz): 用于分析放松/闭眼状态")

# Beta 波提取(13-30 Hz)
# 用途:运动想象、注意力分析
raw_beta = raw_notch.copy().filter(
    l_freq=13, 
    h_freq=30, 
    picks='eeg', 
    verbose=False
)
print("  Beta (13-30 Hz): 用于分析专注/运动想象")

# Theta 波提取(4-8 Hz)
# 用途:认知负荷、记忆研究
raw_theta = raw_notch.copy().filter(
    l_freq=4, 
    h_freq=8, 
    picks='eeg', 
    verbose=False
)
print("  Theta (4-8 Hz): 用于分析记忆/认知负荷")

# 宽频带提取(0.5-45 Hz)
# 用途:通用 ERP 分析
raw_wide = raw_notch.copy().filter(
    l_freq=0.5, 
    h_freq=45, 
    picks='eeg', 
    verbose=False
)
print("  Wideband (0.5-45 Hz): ERP 分析常用频段")

六、滤波前后对比

6.1 创建对比图

python 复制代码
print("\n" + "="*60)
print("滤波效果对比")
print("="*60)

# plt.subplots(2, 2) 创建 2行×2列 的子图布局
# 返回:(图形对象, 子图数组)
# axes[0, 0] = 第1行第1列
# axes[0, 1] = 第1行第2列
# axes[1, 0] = 第2行第1列
# axes[1, 1] = 第2行第2列
fig, axes = plt.subplots(2, 2, figsize=(16, 10))
fig.suptitle('滤波前后对比', fontsize=16, fontweight='bold')

# ---------- 子图1:滤波前频谱 ----------
raw_eeg.plot_psd(
    fmin=0.1,              # 最小频率
    fmax=100,              # 最大频率
    ax=axes[0, 0],         # 画在第1行第1列
    spatial_colors=True,   # 每个通道不同颜色
    show=False             # 不立即显示(等最后统一显示)
)
axes[0, 0].set_title('滤波前 - 原始频谱', fontsize=12)

# axvline() 画竖线标注工频位置
axes[0, 0].axvline(
    x=power_freq,          # 竖线的 x 坐标
    color='red',           # 红色
    linestyle='--',        # 虚线
    alpha=0.7,             # 透明度(0=全透明, 1=不透明)
    label=f'{power_freq}Hz 工频'  # 图例文字
)
axes[0, 0].legend()  # 显示图例

# ---------- 子图2:滤波后频谱 ----------
raw_filtered.plot_psd(
    fmin=0.1, 
    fmax=100, 
    ax=axes[0, 1], 
    spatial_colors=True, 
    show=False
)
axes[0, 1].set_title('滤波后 - 干净频谱', fontsize=12)
axes[0, 1].axvline(
    x=power_freq, 
    color='red', 
    linestyle='--', 
    alpha=0.7, 
    label=f'{power_freq}Hz 已去除'
)
axes[0, 1].legend()

# ---------- 子图3:滤波前时域波形 ----------
# raw_eeg[:10, :5000] 的拆解:
#   [行范围, 列范围]
#   :10 = 取前 10 个通道
#   :5000 = 取前 5000 个采样点
data_before, times = raw_eeg[:10, :5000]

# data_before.T 转置
# 原始形状:(10个通道, 5000个时间点)
# 转置后:(5000个时间点, 10个通道)
# 这样 plot() 可以一次画 10 条线
axes[1, 0].plot(times, data_before.T, alpha=0.7, linewidth=0.5)
axes[1, 0].set_title('滤波前 - 时域波形', fontsize=12)
axes[1, 0].set_xlabel('时间 (秒)')
axes[1, 0].set_ylabel('振幅')

# ---------- 子图4:滤波后时域波形 ----------
data_after, times = raw_filtered[:10, :5000]
axes[1, 1].plot(times, data_after.T, alpha=0.7, linewidth=0.5)
axes[1, 1].set_title('滤波后 - 时域波形', fontsize=12)
axes[1, 1].set_xlabel('时间 (秒)')
axes[1, 1].set_ylabel('振幅')

# tight_layout():自动调整子图间距
# 防止标签和标题重叠
plt.tight_layout()

# savefig():保存图片
plt.savefig('day4_filter_comparison.png', dpi=150, bbox_inches='tight')
print("✅ 对比图已保存为 day4_filter_comparison.png")

plt.show(block=True)

数据索引详解:

python 复制代码
# raw_eeg[通道, 时间] 的用法:

# 获取所有通道、所有时间点
all_data, all_times = raw_eeg[:, :]

# 获取第 0 个通道的所有时间点
ch0_data, times = raw_eeg[0, :]

# 获取前 5 个通道的前 1000 个时间点
subset_data, subset_times = raw_eeg[:5, :1000]

# 获取特定通道列表的前 500 个时间点
specific_data, _ = raw_eeg[['Fz', 'Cz', 'Pz'], :500]

七、重参考

7.1 什么是参考电极?

python 复制代码
print("""
┌────────────────────────────────────────────────┐
│              重参考原理                         │
├────────────────────────────────────────────────┤
│                                                │
│  采集时:每个通道记录的是电位差                 │
│    Ch1_记录 = Ch1_真实 - Ref                   │
│    Ch2_记录 = Ch2_真实 - Ref                   │
│    ...                                         │
│                                                │
│  如果 Ref 本身也有信号(如 Cz 有脑电活动):    │
│    所有通道都混入了 Ref 的活动                  │
│                                                │
│  重参考 = 换一个"参考点"重新计算                │
│    Ch1_新 = Ch1_记录 - 新Ref                   │
│                                                │
│  平均参考:                                     │
│    新Ref = 所有通道的平均值                     │
│    假设:全头平均电位 ≈ 0                       │
└────────────────────────────────────────────────┘
""")

7.2 代码实现

python 复制代码
print("\n" + "="*60)
print("步骤3:重参考")
print("="*60)

# 在滤波后的基础上进行重参考
raw_reref = raw_filtered.copy()

# set_eeg_reference():设置 EEG 参考

# 方法1:平均参考(最常用、最推荐)
raw_reref.set_eeg_reference(
    'average',           # 参考类型:所有通道的平均值
    verbose=False        # 不打印详细信息
)
print("✅ 重参考完成:平均参考")
print(f"当前 EEG 参考已应用: {raw_reref.info['custom_ref_applied']}")

各种重参考方法:

python 复制代码
# ---------- 方法1:平均参考 ----------
# 原理:每个通道减去所有通道的平均值
# 优点:简单、标准、适合高密度电极
# 缺点:如果电极覆盖不全,假设不成立
raw_avg = raw_filtered.copy()
raw_avg.set_eeg_reference('average', verbose=False)

# ---------- 方法2:特定电极参考 ----------
# 以 Fz 为参考
# 原理:所有通道减去 Fz 的值
# Fz 变为 0(自己减自己)
raw_fz_ref = raw_filtered.copy()
raw_fz_ref.set_eeg_reference(['Fz'], verbose=False)

# ---------- 方法3:双耳乳突平均参考 ----------
# 如果数据中有 T9(左乳突)、T10(右乳突)
# 原理:所有通道减去 T9和T10 的平均值
# 优点:传统常用,接近"中性"
# raw_mastoid = raw_filtered.copy()
# raw_mastoid.set_eeg_reference(['T9', 'T10'], verbose=False)

# ---------- 方法4:REST 参考 ----------
# 需要安装:pip install mne_connectivity
# REST = Reference Electrode Standardization Technique
# 优点:数学上等价于"无穷远"参考
# 缺点:需要头模型
# raw_rest = raw_filtered.copy()
# raw_rest.set_eeg_reference('REST', verbose=False)

7.3 重参考前后对比

python 复制代码
print("\n重参考效果对比...")

# 创建一个有 Cz 参考的数据
raw_cz_ref = raw_filtered.copy()
raw_cz_ref.set_eeg_reference(['Cz'], verbose=False)

# 提取相同时间段的数据
# 取第 100 秒附近的数据
time_idx = int(100 * raw_filtered.info['sfreq'])  # 100秒对应的采样点
time_window = int(0.5 * raw_filtered.info['sfreq'])  # 0.5秒的采样点数

# 获取该时间段的数据
data_cz, _ = raw_cz_ref[:, time_idx:time_idx + time_window]
data_avg, _ = raw_reref[:, time_idx:time_idx + time_window]

# 创建对比图
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('重参考前后对比', fontsize=14, fontweight='bold')

# 子图1:Cz参考的地形图(取时间窗中点)
mid_point = time_window // 2
# 先创建一个临时的 Evoked 对象用于画地形图
# (这里简化处理,用 Raw 对象直接画)
info_cz = raw_cz_ref.info
axes[0, 0].set_title('Cz参考时的地形图', fontsize=12)
# 画传感器位置作为示意
raw_cz_ref.plot_sensors(axes=axes[0, 0], show=False)

# 子图2:平均参考的地形图
axes[0, 1].set_title('平均参考后的地形图', fontsize=12)
raw_reref.plot_sensors(axes=axes[0, 1], show=False)

# 子图3:Cz参考的前5个通道波形
times_ms = np.arange(time_window) / raw_filtered.info['sfreq'] * 1000  # 转为毫秒
for i in range(5):
    axes[1, 0].plot(times_ms, data_cz[i, :] * 1e6, linewidth=0.8, 
                    label=raw_cz_ref.ch_names[i])
axes[1, 0].set_title('Cz参考 - 前5通道波形', fontsize=12)
axes[1, 0].set_xlabel('时间 (ms)')
axes[1, 0].set_ylabel('振幅 (μV)')
axes[1, 0].legend(fontsize=8)

# 子图4:平均参考的前5个通道波形
for i in range(5):
    axes[1, 1].plot(times_ms, data_avg[i, :] * 1e6, linewidth=0.8,
                    label=raw_reref.ch_names[i])
axes[1, 1].set_title('平均参考 - 前5通道波形', fontsize=12)
axes[1, 1].set_xlabel('时间 (ms)')
axes[1, 1].set_ylabel('振幅 (μV)')
axes[1, 1].legend(fontsize=8)

plt.tight_layout()
plt.savefig('day4_rereference_comparison.png', dpi=150, bbox_inches='tight')
print("✅ 重参考对比图已保存")
plt.show(block=True)

八、完整预处理流程

8.1 封装为函数

python 复制代码
print("\n" + "="*60)
print("完整预处理流程")
print("="*60)

def preprocess_eeg(raw, power_freq=60, l_freq=1, h_freq=40, reference='average'):
    """
    EEG 数据预处理函数
    
    将四个步骤封装到一个函数中,方便批量处理
    
    参数:
        raw: MNE Raw 对象(原始数据)
        power_freq: 工频频率 (Hz),中国=50,美国=60
        l_freq: 高通截止频率 (Hz)
        h_freq: 低通截止频率 (Hz)
        reference: 参考类型,'average' 或电极名列表
    
    返回:
        预处理后的 Raw 对象
    """
    print("  开始预处理...")
    
    # 步骤1:陷波滤波
    # 去除工频干扰
    print(f"    步骤1: 陷波滤波 (去除 {power_freq}Hz)...")
    raw_proc = raw.copy()
    raw_proc.notch_filter(
        freqs=power_freq, 
        picks='eeg', 
        verbose=False
    )
    
    # 步骤2:带通滤波
    # 保留感兴趣的频率范围
    print(f"    步骤2: 带通滤波 ({l_freq}-{h_freq} Hz)...")
    raw_proc.filter(
        l_freq=l_freq, 
        h_freq=h_freq, 
        picks='eeg', 
        verbose=False
    )
    
    # 步骤3:重参考
    # 统一参考方式
    print(f"    步骤3: 重参考 ({reference})...")
    raw_proc.set_eeg_reference(reference, verbose=False)
    
    print("  ✅ 预处理完成!")
    return raw_proc

# 使用预处理函数
raw_preprocessed = preprocess_eeg(
    raw_eeg,
    power_freq=60,     # 美国数据用 60Hz
    l_freq=1,          # 高通 1Hz
    h_freq=40,         # 低通 40Hz
    reference='average'  # 平均参考
)

# 查看最终结果
print(f"\n预处理后数据信息:")
print(f"  通道数: {len(raw_preprocessed.ch_names)}")
print(f"  采样率: {raw_preprocessed.info['sfreq']} Hz")
print(f"  数据时长: {raw_preprocessed.times[-1]:.1f} 秒")
print(f"  采样点数: {len(raw_preprocessed.times)}")

8.2 保存预处理结果

python 复制代码
# save():将 Raw 对象保存为 .fif 文件
# 下次可以直接加载,不需要重新预处理
raw_preprocessed.save(
    'day4_preprocessed_eeg.fif',

九、第4天完整代码

python 复制代码
# ========== 环境设置 ==========
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import mne
import numpy as np
import os
import warnings
warnings.filterwarnings('ignore')

plt.rcParams['font.sans-serif'] = ['Microsoft YaHei', 'SimHei']
plt.rcParams['axes.unicode_minus'] = False

print("="*60)
print("MNE-Python 第4天:滤波与重参考")
print("="*60)

# ---------- 1. 加载数据 ----------
sample_data_folder = mne.datasets.sample.data_path()
raw_fname = os.path.join(sample_data_folder, 'MEG', 'sample', 'sample_audvis_raw.fif')
raw = mne.io.read_raw_fif(raw_fname, preload=False)

raw_eeg = raw.copy().pick_types(eeg=True)
montage = mne.channels.make_standard_montage('standard_1020')
eeg_names = raw_eeg.ch_names
standard_names = montage.ch_names[:len(eeg_names)]
raw_eeg.rename_channels(dict(zip(eeg_names, standard_names)))
raw_eeg.set_montage(montage)
raw_eeg.load_data()
print("✅ 数据准备完成")

# ---------- 2. 滤波前频谱 ----------
print("\n滤波前频谱...")
raw_eeg.plot_psd(fmin=0.1, fmax=100, spatial_colors=True, average=False)
plt.title('滤波前 PSD', fontsize=14)
plt.show(block=True)

# ---------- 3. 陷波滤波 ----------
print("\n陷波滤波...")
raw_notch = raw_eeg.copy().notch_filter(freqs=60, picks='eeg', verbose=False)
print("✅ 去除了 60Hz 工频干扰")

# ---------- 4. 带通滤波 ----------
print("\n带通滤波...")
raw_filtered = raw_notch.copy().filter(l_freq=1, h_freq=40, picks='eeg', verbose=False)
print("✅ 保留 1-40 Hz")

# ---------- 5. 滤波后频谱 ----------
print("\n滤波后频谱...")
raw_filtered.plot_psd(fmin=0.1, fmax=100, spatial_colors=True, average=False)
plt.title('滤波后 PSD', fontsize=14)
plt.show(block=True)

# ---------- 6. 重参考 ----------
print("\n重参考...")
raw_reref = raw_filtered.copy()
raw_reref.set_eeg_reference('average', verbose=False)
print("✅ 平均参考完成")

# ---------- 7. 保存预处理结果 ----------
raw_reref.save('day4_preprocessed_eeg.fif', overwrite=True)
print("\n✅ 预处理完成,数据已保存为 day4_preprocessed_eeg.fif")

print("\n" + "="*60)
print("第4天学习完成!")
print("="*60)
相关推荐
深度先生10 小时前
pip 与包管理基础——你的第一个包管理工具
python
biter down11 小时前
6:控件操作与鼠标模拟
开发语言·python
沉下去,苦磨练!11 小时前
python的数据分析Pandas
python·数据分析·pandas
import_random11 小时前
[python]numpy.arange()函数的使用
python
aqi0011 小时前
15天学会AI应用开发(五)使用AI摘要来压缩上下文消息
人工智能·python·大模型·ai编程·ai应用
叶梓翎11 小时前
AI语义搜索本地素材一键整合包官方下载
人工智能·python·图搜索
敲代码的小王!11 小时前
Python 核心语法 —— 数据、流程与容器
开发语言·python
chéng ௹11 小时前
python将word文档转化成html
python·html·word
覆东流11 小时前
python环境搭建
开发语言·python