大论文也算是写完交一段时间了,回想自己每次要画图的时候也是满世界找方案(GPT问的最多😅)。虽然以后99%不会再画这些图了,但是还是想把论文用到的一些绘图代码记录在此,也许会有有缘人需要🤣🤣🤣。


本文可以学到哪些

在正式进入主题之前,先介绍一下Python读取MAT文件数据的方法。因为本人的实验数据都是MATLAB跑出来的结果,存放在MAT文件中。Python读取并绘图的时候出现了一些问题,在这里记录下。此后,便是一系列绘图示例。

Python读取MAT文件

出现的问题

  1. 一般来说,我都是用Scipy库的io模块进行MAT文件的读取。scipy.io 模块是 Scipy 库中的一个子模块,用于处理输入输出操作。它提供了许多函数来读取和写入各种格式的文件,包括 MATLAB 文件、wav 文件、图像文件等。下面是一些 scipy.io 模块中常用的功能:

    • scipy.io.loadmat():用于加载 MATLAB 格式的 .mat 文件。

    • scipy.io.savemat():用于保存数据到 MATLAB 格式的 .mat 文件。

    • scipy.io.wavfile.read():用于读取 WAV 音频文件。

    • scipy.io.wavfile.write():用于写入数据到 WAV 音频文件。

    • scipy.io.load():通用的加载函数,支持多种文件格式,如 .wav、.png、.jpg 等。

    • scipy.io.save():通用的保存函数,支持多种文件格式,如 .wav、.png、.jpg 等。

  2. 但是直到出现这个报错:从报错信息中可以看出是因为MATLAB保存MAT文件使用的是v7.3或更高的版本保存的,换成h5py读取就可以了。可以参考这篇文章的介绍: 使用python读取Matlab的.mat文件 常见问题

    读取MAT文件报错

混淆矩阵类

模型分组示例

  1. 代码实现:

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib.colors import ListedColormap
    import matplotlib.patches as mpatches
    
    # 创建模拟数据
    data_A = np.array([[70, 70, 70, 30, 30, 30],
                    [30, 30, 30, 10, 10, 10]])
    # 自定义颜色列表
    colors = ['skyblue', 'white', 'salmon']  # 每个矩阵块对应的颜色
    
    # 创建自定义颜色映射
    cmap_custom = ListedColormap(colors)
    
    # 设置图片尺寸
    fig, ax = plt.subplots(dpi = 300)
    
    # 绘制热力图,并根据自定义颜色映射显示
    im = ax.imshow(data_A, cmap=cmap_custom)
    
    # 设置坐标轴刻度和标签
    ax.set_xticks(np.arange(6))
    ax.set_xticklabels(['1', '2', '3', '4', '5', '6'])
    ax.set_yticks(np.arange(2))
    ax.set_yticklabels(['Group 1', 'Group 2'])
    
    # 设置坐标轴标签
    ax.set_xlabel('Models', weight='bold')
    ax.set_ylabel('Families', weight='bold')  
    
    # 添加图形标题
    ax.set_title("Families' partition", weight='bold')  
    legend_elements = [mpatches.Patch(facecolor='skyblue', edgecolor='black', label='DoG Models'),
                    mpatches.Patch(facecolor='salmon', edgecolor='black', label='Gauss Models')]
    ax.legend(handles=legend_elements, loc='upper right')
    # 调整子图布局以防止标签被剪裁
    plt.tight_layout()
    # 显示图形
    plt.show()
  2. 示例结果

模型分组示例

模型块对应不同值

  1. 代码示例

    import numpy as np
    import matplotlib.pyplot as plt
    
    # 设置全局字体和字号
    plt.rcParams.update({'font.family': 'sans-serif', 'font.size': 12})
    
    # 创建相关矩阵数据
    data_A = np.array([[0.36, 0.29, 0.07],
                    [0.16, 0.11, 0.01]])
    
    data_B = np.array([[1.00, 0, 0],
                    [0, 0, 0]])
    
    # 绘制A图
    fig, ax1 = plt.subplots(1, 1, figsize=(5, 4),dpi = 300)
    im_A = ax1.imshow(data_A, interpolation='nearest', cmap=plt.cm.Blues)
    cbar_A = plt.colorbar(im_A)
    ax1.set_xticks(np.arange(data_A.shape[1]))
    ax1.set_yticks(np.arange(data_A.shape[0]))
    ax1.set_xticklabels(['1', '2', '3'], fontweight='bold')
    ax1.set_yticklabels(['DoG', 'Gauss'], fontweight='bold', verticalalignment='center')
    
    for i in range(data_A.shape[0]):
        for j in range(data_A.shape[1]):
            text_color = 'black'
            if i == 0 and j == 0:
                text_color = 'white'
            text = ax1.text(j, i, data_A[i, j], ha='center', va='center', color=text_color)
    
    ax1.set_title('Model probabilities', fontweight='bold', pad=20)
  2. 示例结果

类似混淆矩阵

小提琴图

两(多)组数据

  1. 代码示例

    import matplotlib.pyplot as plt
    import seaborn as sns
    import numpy as np
    
    # 生成随机数据
    np.random.seed(0)
    data1 = np.random.normal(loc=0, scale=1, size=100)  # 左脑数据
    data2 = np.random.normal(loc=0, scale=1, size=100)  # 右脑数据
    
    # 绘制小提琴图
    plt.figure(figsize=(5, 5))
    sns.violinplot(data=[data1, data2], palette=['#FF5D5C', '#0D5BFF'], alpha=0.7)
    
    # 设置图形参数
    plt.ylabel("Eccentricity", fontsize=16)
    plt.xticks(ticks=[0, 1], labels=["Left hemisphere", "Right hemisphere"], fontsize=14)
    
    # 显示图形
    plt.show()
  2. 示例结果

两组数据绘制

两(多)组比较

  1. 代码示例

    import matplotlib.pyplot as plt
    import numpy as np
    import seaborn as sns
    import pandas as pd
    
    # 生成随机数据
    np.random.seed(0)
    data1 = np.random.normal(loc=0, scale=1, size=100)  # 随机生成左脑数据1
    data2 = np.random.normal(loc=0, scale=1, size=100)  # 随机生成左脑数据2
    data3 = np.random.normal(loc=0, scale=1, size=100)  # 随机生成右脑数据1
    data4 = np.random.normal(loc=0, scale=1, size=100)  # 随机生成右脑数据2
    
    # 构建数据框
    df1 = pd.DataFrame({'Data': data1, 'Group': ['Group 1'] * len(data1), 'Subgroup': ['Subgroup 1'] * len(data1)})
    df2 = pd.DataFrame({'Data': data2, 'Group': ['Group 1'] * len(data2), 'Subgroup': ['Subgroup 2'] * len(data2)})
    df3 = pd.DataFrame({'Data': data3, 'Group': ['Group 2'] * len(data3), 'Subgroup': ['Subgroup 1'] * len(data3)})
    df4 = pd.DataFrame({'Data': data4, 'Group': ['Group 2'] * len(data4), 'Subgroup': ['Subgroup 2'] * len(data4)})
    
    # 合并数据框
    df = pd.concat([df1, df2, df3, df4])
    colors = ["#FF5D5C", "#0D5BFF"]
    
    # 绘制小提琴图
    plt.figure(figsize=(5, 5))
    ax = sns.violinplot(x='Group', y='Data', hue='Subgroup', data=df, split=True, inner='quartile', palette=colors, alpha=0.6)
    
    # 设置图形参数
    plt.xticks(ticks=[0, 1], labels=['Left Hemisphere', 'Right Hemisphere'], fontsize=14)
    plt.xlabel('')
    plt.ylabel('Eccentricity (deg)', fontsize=16)
    legend = ax.legend(fontsize=13, loc='upper right', bbox_to_anchor=(1.35, 1))
    legend.get_texts()[0].set_text("Split1")
    legend.get_texts()[1].set_text("Split2")
    plt.show()
  2. 示例结果

带有比较的

极角直方图

极角直方图没有什么难度,但是如果想在直方图的外圈添加Colorbar又该如何实现那?

参考链接: Plot a (polar) color wheel based on a colormap using Python/Matplotlib

  1. 实现代码

    import matplotlib.pyplot as plt
    import numpy as np
    from matplotlib import cm
    import matplotlib as mpl
    import seaborn as sns
    sns.set_style('ticks')
    
    fig = plt.figure(figsize=(5,5))
    # 随机数据
    ang1 = np.random.uniform(-np.pi/2, np.pi /2 , size=1000)
    ang2 = np.random.uniform(np.pi/2 , np.pi * 3 / 2, size=1000)
    
    # 绘制环形的Colorbar
    display_axes = fig.add_axes([0.1, 0.1, 0.8, 0.8], projection='polar')
    norm = mpl.colors.Normalize(np.pi, 3 * np.pi)
    quant_steps = 2056
    cb = mpl.colorbar.ColorbarBase(display_axes,
                                cmap=cm.get_cmap('hsv_r', quant_steps),
                                norm=norm,
                                orientation='horizontal')
    cb.outline.set_visible(False)
    display_axes.set_axis_off()
    
    # 在大的极坐标子图上绘制直方图
    ax = fig.add_axes([0.15, 0.15, 0.7, 0.7], projection='polar')  # 调整位置和大小
    
    ax.hist(ang1, bins=30, color='#FF5D5C', edgecolor='none',alpha=0.7, density=True,label = 'Left hemisphere')
    ax.hist(ang2, bins=30, color='#0D5BFF', edgecolor='none',alpha=0.7, density=True,label = 'Right hemisphere')
    ax.set_rticks([0.2, 0.5])  # 设置只显示0.5和1.0两个标签
    ax.set_xticklabels([])
    ax.spines['polar'].set_visible(False)
    # plt.text(-0.1, 1.07, 'A', transform=ax.transAxes, fontsize=18, fontweight='bold', va='top')
    plt.legend(loc='upper right',fontsize = 14)
  2. 结果示例

带有环形Colorbar的极角直方图

均值误差图(带有显著标识)

  1. 代码实现

    import numpy as np
    import seaborn as sns
    import scipy.stats as stats
    import matplotlib.pyplot as plt
    plt.rcParams['font.size'] = 16
    
    # 生成随机数据
    np.random.seed(0)
    group1 = np.random.normal(loc=10, scale=3, size=100)
    group2 = np.random.normal(loc=12, scale=3, size=100)
    
    # 计算均值和标准误差
    mean_group1 = np.mean(group1)
    mean_group2 = np.mean(group2)
    sem_group1 = stats.sem(group1)
    sem_group2 = stats.sem(group2)
    
    plt.figure(figsize=(6,5))
    
    bar = plt.bar(['Contralateral', 'Ipsilateral'], [mean_group1, mean_group2], yerr=[sem_group1, sem_group2], capsize=12, color=['salmon','skyblue'])
    plt.ylabel('Explained variance (mean)')
    plt.title('Right hemisphere',y=1.02)
    
    # 添加显著性标注
    gap = 2.5 # 显著性标注与最大高度的距离
    t = max(mean_group1, mean_group2) + gap
    plt.axhline(y=t, xmin=0.25, xmax=0.75, color='black', linestyle='-', linewidth=2)
    plt.plot([0, 0], [t, t - 0.3], color='black')
    plt.plot([1, 1], [t, t - 0.3], color='black')
    plt.text(0.5, t + 0.1, '***', fontsize=14, fontweight='bold')
    
    # 在柱形图顶部标记均值和标准误差
    text_gap = 0.5  # 数值标记的高度
    for i, rect in enumerate(bar):
        height = rect.get_height()
        plt.text(rect.get_x() + rect.get_width()/2, height + text_gap, f'{height:.2f} ± {sem_group1 if i == 0 else sem_group2:.2f}', ha='center', va='bottom')
    
    plt.ylim(0, 17)
    plt.show()
  2. 结果示例

带有显著标识的均值误差图

平均曲线以及置信区间

  1. 代码实现(仅作自用,不多解释)

    import pandas as pd
    import numpy as np
    import seaborn as sns
    import matplotlib.pyplot as plt
    import scipy.io as scio
    import h5py
    # 假设有一个数据框 data_df,其中每列代表一个样本曲线的观测值
    dataFile = 'E:\\我的论文\\00-论文写作\\AA_sub_half_HRF_12_DOG1_th.mat' 
    mat_data = h5py.File(dataFile,'r')
    data_df = pd.DataFrame(mat_data['hrf_t1'])
    plt.rcParams['font.size'] = 16
    plt.figure(figsize=(9, 6))
    # 计算每个样本曲线的均值和标准误差
    # 计算每组数据的均值和标准误差
    # data_df= data_df.loc[:,:]
    mean_values = data_df.mean()
    se_values = data_df.apply(lambda x: np.std(x) / np.sqrt(len(x)))
    
    # 计算置信区间
    lower_ci = mean_values - 1.96 * se_values
    upper_ci = mean_values + 1.96 * se_values
    
    # 创建x轴的刻度
    x_values = np.arange(1, len(mean_values)+1)
    
    # 创建数据框
    data_plot = pd.DataFrame({'x': x_values, 'mean': mean_values, 'lower_ci': lower_ci, 'upper_ci': upper_ci})
    
    # 绘制均值曲线和置信区间
    
    plt.plot(data_plot['x'] / 16, data_plot['mean'], color='#E07E35', linewidth=1.1,label = 'DoG-1 HRF')
    plt.fill_between(data_plot['x'] / 16, data_plot['lower_ci'], data_plot['upper_ci'], color='#E07E35', alpha=0.5)
    
    # dataFile = 'E:\\我的论文\\00-论文写作\\hrf_th_dog2.mat' 
    # mat_data = h5py.File(dataFile,'r')
    data_df = pd.DataFrame(mat_data['hrf_t2'])
    # 计算每个样本曲线的均值和标准误差
    # 计算每组数据的均值和标准误差
    # data_df= data_df.loc[:,:]
    mean_values = data_df.mean()
    se_values = data_df.apply(lambda x: np.std(x) / np.sqrt(len(x)))
    
    # 计算置信区间
    lower_ci = mean_values - 1.96 * se_values
    upper_ci = mean_values + 1.96 * se_values
    
    # 创建x轴的刻度
    x_values = np.arange(1, len(mean_values)+1)
    
    # 创建数据框
    data_plot = pd.DataFrame({'x': x_values, 'mean': mean_values, 'lower_ci': lower_ci, 'upper_ci': upper_ci})
    
    # 绘制均值曲线和置信区间
    
    plt.plot(data_plot['x'] / 16, data_plot['mean'], color='#0D5BFF', linewidth=1.1,label = 'DoG-2 HRF',linestyle = 'dashdot')
    plt.fill_between(data_plot['x'] / 16, data_plot['lower_ci'], data_plot['upper_ci'], color='#0D5BFF', alpha=0.3)
    
    
    dataFile = 'E:\\我的论文\\00-论文写作\\caonical_hrf.mat' 
    mat_data = h5py.File(dataFile,'r')
    data_df = pd.DataFrame(mat_data['t'])
    mean_values = data_df.mean()
    x_values = np.arange(1, len(mean_values)+1)
    
    se_values = data_df.apply(lambda x: np.std(x) / np.sqrt(len(x)))
    data_plot = pd.DataFrame({'x': x_values, 'mean': mean_values})
    plt.plot(data_plot['x'] / 16, data_plot['mean'], color='red', linewidth=1.2,label = 'Canonical HRF',linestyle='dashed')
    
    # 设置图形属性
    plt.xlabel('Time (s)')
    plt.ylabel('Amplitude (a.u.)')
    plt.title('Hemodynamic Variability', loc='center', fontsize=16, fontweight='bold')
    plt.grid(True)
    plt.legend(fontsize = 13)
    # plt.savefig('hrf_wm_.pdf', format='pdf', bbox_inches='tight',pad_inches=0)
    # plt.yticks(np.arange(0, 1,8))
    plt.show()
  2. 结果示例

均值曲线以及置信区间

图片添加序号

  1. 代码实现

    • 这个位置什么的只能一点点尝试了~

      plt.text(-0.13, 1.13, 'A', transform=ax.transAxes, fontsize=18, fontweight='bold', va='top')

最后的最后

GPT是个好东西,没事多用用~


$\cdots$ 什么都略懂一点,生活更多彩一些 $\cdots$

$\cdots$ end $\cdots$