为什么下面的代码里,最后面的print函数里的中文输出无法正常显示:
# encoding: utf-8
import scipy.io
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
import matplotlib as mpl
import matplotlib.font_manager as fm
import pandas as pd
import seaborn as sns
import os
from pathlib import Path
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体显示中文
plt.rcParams['axes.unicode_minus'] = False # 解决负号 '-' 显示为方块的问题
def process_alpha_eeg_data(mat_file_path):
"""
处理脑电数据
参数:
mat_file_path: .mat文件路径
返回:
fig: 生成的图表对象
results_df: 包含所有分析结果的DataFrame
"""
# 1. .mat文件数据
mat_data = scipy.io.loadmat(mat_file_path)
# 2. 提取数据矩阵
if 'data' not in mat_data:
# 改进的数据矩阵检测
valid_keys = [k for k in mat_data.keys()
if not k.startswith('__')
and isinstance(mat_data[k], np.ndarray)
and mat_data[k].ndim == 2]
if not valid_keys:
raise ValueError("未找到有效的二维数据矩阵")
# 选择最大的数据矩阵
data_matrix = mat_data[max(valid_keys, key=lambda k: mat_data[k].size)]
print(f"使用自动检测到的数据矩阵: {max(valid_keys, key=lambda k: mat_data[k].size)}")
else:
data_matrix = mat_data['data']
# 3. 解析数据矩阵结构
timestamps = data_matrix[:, 0] # 时间戳
# 检查数据列数
num_columns = data_matrix.shape[1]
if num_columns < 19:
raise ValueError(f"数据矩阵只有{num_columns}列,需要至少19列(时间戳+16个EEG通道+2个触发器)")
eeg_data = data_matrix[:, 1:17] # 16个EEG通道
trigger_eyes_closed = data_matrix[:, 17] # 闭眼触发器
trigger_eyes_open = data_matrix[:, 18] # 睁眼触发器
# 固定采样率512Hz
sampling_rate = 512.0
# 4. 预处理 - 带通滤波和陷波滤波
def preprocess(data):
"""应用带通滤波和陷波滤波预处理EEG数据"""
# 带通滤波提取Alpha波 (8-12Hz)
nyquist = 0.5 * sampling_rate
low = 8 / nyquist
high = 12 / nyquist
b, a = signal.butter(4, [low, high], btype='bandpass')
alpha_data = signal.filtfilt(b, a, data)
# 陷波滤波去除50/60Hz工频干扰
notch_freq = 50.0 # 根据实际工频干扰调整
notch_width = 2.0
freq = notch_freq / nyquist
q = freq / (notch_width / nyquist)
b, a = signal.iirnotch(freq, q)
return signal.filtfilt(b, a, alpha_data)
# 应用预处理到所有通道
eeg_data_filtered = np.apply_along_axis(preprocess, 0, eeg_data)
# 5. 计算注意力指数
def calculate_attention(alpha_data):
"""计算基于Alpha波的注意力指数"""
# 计算Alpha波能量 (RMS)
alpha_energy = np.sqrt(np.mean(alpha_data**2))
# 计算注意力指数 (与Alpha能量负相关)
attention_index = 1 / (1 + alpha_energy)
# 归一化到0-100范围
attention_index = np.clip(attention_index * 100, 0, 100)
return attention_index
# 6. 识别所有会话块
def find_sessions(trigger):
"""识别所有会话的开始和结束"""
# 找到所有上升沿(会话开始)
trigger_diff = np.diff(trigger)
session_starts = np.where(trigger_diff == 1)[0] + 1
# 找到所有下降沿(会话结束)
session_ends = np.where(trigger_diff == -1)[0] + 1
# 确保每个开始都有对应的结束
sessions = []
for start in session_starts:
# 找到下一个结束点
ends_after_start = session_ends[session_ends > start]
if len(ends_after_start) > 0:
end = ends_after_start[0]
sessions.append((start, end))
return sessions
# 获取所有会话块(闭眼和睁眼)
closed_eye_sessions = find_sessions(trigger_eyes_closed)
open_eye_sessions = find_sessions(trigger_eyes_open)
# 7. 处理每个会话块
session_results = []
# 处理闭眼会话块
for session_idx, (start_idx, end_idx) in enumerate(closed_eye_sessions):
# 提取会话数据
session_eeg = eeg_data_filtered[start_idx:end_idx, :]
session_duration = (end_idx - start_idx) / sampling_rate
# 计算平均注意力指数(所有通道)
channel_attention = []
for ch in range(session_eeg.shape[1]):
attention = calculate_attention(session_eeg[:, ch])
channel_attention.append(attention)
session_avg_attention = np.mean(channel_attention)
# 存储会话结果
session_results.append({
'session_id': session_idx + 1,
'condition': '闭眼',
'start_time': timestamps[start_idx],
'duration': session_duration,
'avg_attention': session_avg_attention,
'channel_attention': channel_attention
})
# 处理睁眼会话块
for session_idx, (start_idx, end_idx) in enumerate(open_eye_sessions):
# 提取会话数据
session_eeg = eeg_data_filtered[start_idx:end_idx, :]
session_duration = (end_idx - start_idx) / sampling_rate
# 计算平均注意力指数(所有通道)
channel_attention = []
for ch in range(session_eeg.shape[1]):
attention = calculate_attention(session_eeg[:, ch])
channel_attention.append(attention)
session_avg_attention = np.mean(channel_attention)
# 存储会话结果
session_results.append({
'session_id': session_idx + 1 + len(closed_eye_sessions),
'condition': '睁眼',
'start_time': timestamps[start_idx],
'duration': session_duration,
'avg_attention': session_avg_attention,
'channel_attention': channel_attention
})
# 创建结果DataFrame
results_df = pd.DataFrame(session_results)
# 8. 简化可视化结果 - 只保留两个图表
fig = plt.figure(figsize=(16, 10), constrained_layout=True)
gs = fig.add_gridspec(2, 1) # 2行1列布局
# 图1: 随时间变化的注意力指数
ax1 = fig.add_subplot(gs[0, 0])
# 为不同条件设置不同颜色
colors = {'闭眼': 'blue', '睁眼': 'orange'}
for condition in ['闭眼', '睁眼']:
condition_data = results_df[results_df['condition'] == condition]
ax1.plot(condition_data['session_id'], condition_data['avg_attention'],
'o-', label=condition, markersize=8, color=colors[condition])
ax1.set_title('不同条件下注意力指数随时间变化', fontsize=16)
ax1.set_xlabel('会话块编号', fontsize=14)
ax1.set_ylabel('平均注意力指数 (%)', fontsize=14)
ax1.legend(fontsize=12)
ax1.grid(True, linestyle='--', alpha=0.3)
# 添加每个数据点的数值标签
for _, row in results_df.iterrows():
ax1.text(row['session_id'], row['avg_attention'] + 2,
f"{row['avg_attention']:.1f}",
ha='center', va='bottom', fontsize=9)
# 图2: 闭眼与睁眼条件下的注意力比较
ax2 = fig.add_subplot(gs[1, 0])
# 箱线图展示条件间差异
sns.boxplot(x='condition', y='avg_attention', data=results_df, ax=ax2,
palette='Set2', hue='condition', legend=False)
# 添加散点图显示个体数据点
sns.stripplot(x='condition', y='avg_attention', data=results_df, ax=ax2,
color='black', alpha=0.7, size=7, jitter=True)
ax2.set_title('闭眼与睁眼条件下注意力比较', fontsize=16)
ax2.set_xlabel('条件', fontsize=14)
ax2.set_ylabel('平均注意力指数 (%)', fontsize=14)
# 添加统计显著性标记(使用独立样本t检验)
from scipy import stats
closed_data = results_df[results_df['condition'] == '闭眼']['avg_attention']
open_data = results_df[results_df['condition'] == '睁眼']['avg_attention']
t_stat, p_value = stats.ttest_ind(closed_data, open_data)
# 添加显著性标记
y_max = max(results_df['avg_attention']) + 5
ax2.plot([0, 0, 1, 1], [y_max, y_max+2, y_max+2, y_max], lw=1.5, c='black')
ax2.text(0.5, y_max+3, f"p = {p_value:.4f}", ha='center', va='bottom', fontsize=12)
plt.tight_layout()
# 9. 保存结果
base_name = os.path.splitext(os.path.basename(mat_file_path))[0]
# 保存图像
fig.savefig(f"{base_name}_analysis.png", dpi=300, bbox_inches='tight')
# 保存结果到CSV
results_df.to_csv(f"{base_name}_results.csv", index=False, encoding='utf-8-sig')
return fig, results_df, p_value
# 使用示例
if __name__ == "__main__":
# 中文路径示例
mat_file = "F:/Grade2/attention/2348892/subject_02.mat"
try:
# 处理数据并生成可视化
fig, results_df, p_value = process_alpha_eeg_data(mat_file)
# 显示图像
plt.show()
# 打印会话结果和统计显著性
print("EEG分析结果:")
print(results_df[['session_id', 'condition', 'duration', 'avg_attention']])
print(f"\n统计显著性结果: p = {p_value:.4f}")
if p_value < 0.05:
print("闭眼与睁眼条件下的注意力指数存在显著差异 (p < 0.05)")
else:
print("闭眼与睁眼条件下的注意力指数无显著差异")
except Exception as e:
print(f"处理过程中发生错误: {str(e)}")
import traceback
traceback.print_exc()