跳转至

API

plotfig.bar

plot_one_group_bar_figure

plot_one_group_bar_figure(data, ax=None, labels_name=None, colors=None, edgecolor=None, gradient_color=False, colors_start=None, colors_end=None, dots_color=None, y_lim=None, width=0.5, color_alpha=1, dots_size=35, errorbar_type='sd', title_name='', title_fontsize=12, title_pad=10, x_label_name='', x_label_ha='center', x_label_fontsize=10, x_tick_fontsize=8, x_tick_rotation=0, y_label_name='', y_label_fontsize=10, y_tick_fontsize=8, y_tick_rotation=0, statistic=False, test_method=['ttest_ind'], p_list=None, popmean=0, statistical_line_color='0.5', asterisk_fontsize=10, asterisk_color='k', ax_bottom_is_0=False, y_max_tick_is_1=False, math_text=True, one_decimal_place=False, percentage=False)

绘制单组柱状图,包含散点、误差条和统计显著性标记。

Parameters:

Name Type Description Default
data ndarray | Sequence[Sequence[Num] | ndarray]

输入数据,可以是二维numpy数组或嵌套序列,每个子序列代表一个柱状图的数据点

required
ax Axes | None

matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.

None
labels_name list[str] | None

柱状图的标签名称列表. Defaults to None.

None
colors list[str] | None

柱状图的颜色列表. Defaults to None.

None
edgecolor str | None

柱状图边缘颜色. Defaults to None.

None
gradient_color bool

是否使用渐变颜色填充柱状图. Defaults to False.

False
colors_start list[str] | None

渐变色的起始颜色列表. Defaults to None.

None
colors_end list[str] | None

渐变色的结束颜色列表. Defaults to None.

None
dots_color list[list[str]] | None

散点的颜色列表. Defaults to None.

None
y_lim list[Num] | tuple[Num, Num] | None

Y轴的范围限制. Defaults to None.

None
width Num

柱状图的宽度. Defaults to 0.5.

0.5
color_alpha Num

柱状图颜色的透明度. Defaults to 1.

1
dots_size Num

散点的大小. Defaults to 35.

35
errorbar_type str

误差条类型,可选 "sd"(标准差) 或 "se"(标准误). Defaults to "sd".

'sd'
title_name str

图表标题. Defaults to "".

''
title_fontsize Num

标题字体大小. Defaults to 12.

12
title_pad Num

标题与图表的间距. Defaults to 10.

10
x_label_name str

X轴标签名称. Defaults to "".

''
x_label_ha str

X轴标签的水平对齐方式. Defaults to "center".

'center'
x_label_fontsize Num

X轴标签字体大小. Defaults to 10.

10
x_tick_fontsize Num

X轴刻度字体大小. Defaults to 8.

8
x_tick_rotation Num

X轴刻度旋转角度. Defaults to 0.

0
y_label_name str

Y轴标签名称. Defaults to "".

''
y_label_fontsize Num

Y轴标签字体大小. Defaults to 10.

10
y_tick_fontsize Num

Y轴刻度字体大小. Defaults to 8.

8
y_tick_rotation Num

Y轴刻度旋转角度. Defaults to 0.

0
statistic bool

是否进行统计显著性分析. Defaults to False.

False
test_method list[str]

统计检验方法列表. Defaults to ["ttest_ind"].

['ttest_ind']
p_list list[float] | None

预计算的p值列表,用于显著性标记. Defaults to None.

None
popmean Num

单样本t检验的假设均值. Defaults to 0.

0
statistical_line_color str

显著性标记线的颜色. Defaults to "0.5".

'0.5'
asterisk_fontsize Num

显著性星号的字体大小. Defaults to 10.

10
asterisk_color str

显著性星号的颜色. Defaults to "k".

'k'
ax_bottom_is_0 bool

Y轴是否从0开始. Defaults to False.

False
y_max_tick_is_1 bool

Y轴最大刻度是否限制为1. Defaults to False.

False
math_text bool

是否将Y轴显示为科学计数法格式. Defaults to True.

True
one_decimal_place bool

Y轴刻度是否只保留一位小数. Defaults to False.

False
percentage bool

是否将Y轴显示为百分比格式. Defaults to False.

False

Raises:

Type Description
ValueError

当data数据格式无效时抛出

ValueError

当errorbar_type不是"sd"或"se"时抛出

Returns:

Type Description
Axes | None

Axes | None: 返回matplotlib的坐标轴对象或None

Source code in src/plotfig/bar.py
def plot_one_group_bar_figure(
    data: np.ndarray | Sequence[Sequence[Num] | np.ndarray],
    ax: Axes | None = None,
    labels_name: list[str] | None = None,
    colors: list[str] | None = None,
    edgecolor: str | None = None,
    gradient_color: bool = False,
    colors_start: list[str] | None = None,
    colors_end: list[str] | None = None,
    dots_color: list[list[str]] | None = None,
    y_lim: list[Num] | tuple[Num, Num] | None = None,
    width: Num = 0.5,
    color_alpha: Num = 1,
    dots_size: Num = 35,
    errorbar_type: str = "sd",
    title_name: str = "",
    title_fontsize: Num = 12,
    title_pad: Num = 10,
    x_label_name: str = "",
    x_label_ha: str = "center",
    x_label_fontsize: Num = 10,
    x_tick_fontsize: Num = 8,
    x_tick_rotation: Num = 0,
    y_label_name: str = "",
    y_label_fontsize: Num = 10,
    y_tick_fontsize: Num = 8,
    y_tick_rotation: Num = 0,
    statistic: bool = False,
    test_method: list[str] = ["ttest_ind"],
    p_list: list[float] | None = None,
    popmean: Num = 0,
    statistical_line_color: str = "0.5",
    asterisk_fontsize: Num = 10,
    asterisk_color: str = "k",
    ax_bottom_is_0: bool = False,
    y_max_tick_is_1: bool = False,
    math_text: bool = True,
    one_decimal_place: bool = False,
    percentage: bool = False,
) -> Axes | None:
    """绘制单组柱状图,包含散点、误差条和统计显著性标记。

    Args:
        data (np.ndarray | Sequence[Sequence[Num] | np.ndarray]):
            输入数据,可以是二维numpy数组或嵌套序列,每个子序列代表一个柱状图的数据点
        ax (Axes | None, optional):
            matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.
        labels_name (list[str] | None, optional):
            柱状图的标签名称列表. Defaults to None.
        colors (list[str] | None, optional):
            柱状图的颜色列表. Defaults to None.
        edgecolor (str | None, optional):
            柱状图边缘颜色. Defaults to None.
        gradient_color (bool, optional):
            是否使用渐变颜色填充柱状图. Defaults to False.
        colors_start (list[str] | None, optional):
            渐变色的起始颜色列表. Defaults to None.
        colors_end (list[str] | None, optional):
            渐变色的结束颜色列表. Defaults to None.
        dots_color (list[list[str]] | None, optional):
            散点的颜色列表. Defaults to None.
        y_lim (list[Num] | tuple[Num, Num] | None, optional):
            Y轴的范围限制. Defaults to None.
        width (Num, optional):
            柱状图的宽度. Defaults to 0.5.
        color_alpha (Num, optional):
            柱状图颜色的透明度. Defaults to 1.
        dots_size (Num, optional):
            散点的大小. Defaults to 35.
        errorbar_type (str, optional):
            误差条类型,可选 "sd"(标准差) 或 "se"(标准误). Defaults to "sd".
        title_name (str, optional):
            图表标题. Defaults to "".
        title_fontsize (Num, optional):
            标题字体大小. Defaults to 12.
        title_pad (Num, optional):
            标题与图表的间距. Defaults to 10.
        x_label_name (str, optional):
            X轴标签名称. Defaults to "".
        x_label_ha (str, optional):
            X轴标签的水平对齐方式. Defaults to "center".
        x_label_fontsize (Num, optional):
            X轴标签字体大小. Defaults to 10.
        x_tick_fontsize (Num, optional):
            X轴刻度字体大小. Defaults to 8.
        x_tick_rotation (Num, optional):
            X轴刻度旋转角度. Defaults to 0.
        y_label_name (str, optional):
            Y轴标签名称. Defaults to "".
        y_label_fontsize (Num, optional):
            Y轴标签字体大小. Defaults to 10.
        y_tick_fontsize (Num, optional):
            Y轴刻度字体大小. Defaults to 8.
        y_tick_rotation (Num, optional):
            Y轴刻度旋转角度. Defaults to 0.
        statistic (bool, optional):
            是否进行统计显著性分析. Defaults to False.
        test_method (list[str], optional):
            统计检验方法列表. Defaults to ["ttest_ind"].
        p_list (list[float] | None, optional):
            预计算的p值列表,用于显著性标记. Defaults to None.
        popmean (Num, optional):
            单样本t检验的假设均值. Defaults to 0.
        statistical_line_color (str, optional):
            显著性标记线的颜色. Defaults to "0.5".
        asterisk_fontsize (Num, optional):
            显著性星号的字体大小. Defaults to 10.
        asterisk_color (str, optional):
            显著性星号的颜色. Defaults to "k".
        ax_bottom_is_0 (bool, optional):
            Y轴是否从0开始. Defaults to False.
        y_max_tick_is_1 (bool, optional):
            Y轴最大刻度是否限制为1. Defaults to False.
        math_text (bool, optional):
            是否将Y轴显示为科学计数法格式. Defaults to True.
        one_decimal_place (bool, optional):
            Y轴刻度是否只保留一位小数. Defaults to False.
        percentage (bool, optional):
            是否将Y轴显示为百分比格式. Defaults to False.

    Raises:
        ValueError: 当data数据格式无效时抛出
        ValueError: 当errorbar_type不是"sd"或"se"时抛出

    Returns:
        Axes | None: 返回matplotlib的坐标轴对象或None
    """
    # 处理None值
    if not _is_valid_data(data):
        raise ValueError("无效的 data")
    ax = ax or plt.gca()
    labels_name = labels_name or [str(i) for i in range(len(data))]
    colors = colors or ["gray"] * len(data)
    # 统一参数型
    width = float(width)
    color_alpha = float(color_alpha)
    dots_size = float(dots_size)
    title_fontsize = float(title_fontsize)
    title_pad = float(title_pad)
    x_label_fontsize = float(x_label_fontsize)
    x_tick_fontsize = float(x_tick_fontsize)
    x_tick_rotation = float(x_tick_rotation)
    y_label_fontsize = float(y_label_fontsize)
    y_tick_fontsize = float(y_tick_fontsize)
    y_tick_rotation = float(y_tick_rotation)
    popmean = float(popmean)
    asterisk_fontsize = float(asterisk_fontsize)

    x_positions = np.arange(len(labels_name))
    means, sds, ses = [], [], []
    scatter_positions = []
    for i, d in enumerate(data):
        mean, sd, se = _compute_summary(d)
        means.append(mean)
        sds.append(sd)
        ses.append(se)
        scatter_x = RNG.normal(i, 0.1, len(d))
        scatter_positions.append(scatter_x)
    if errorbar_type == "sd":
        error_values = sds
    elif errorbar_type == "se":
        error_values = ses
    else:
        raise ValueError("errorbar_type 只能是 'sd' 或者 'se'")

    # 绘制柱子
    if gradient_color:
        if colors_start is None:  # 默认颜色
            colors_start = ["#e38a48"] * len(x_positions)  # 左边颜色
        if colors_end is None:  # 默认颜色
            colors_end = ["#4573a5"] * len(x_positions)  # 右边颜色
        for x, h, c1, c2 in zip(x_positions, means, colors_start, colors_end):
            # 生成线性渐变 colormap
            cmap = LinearSegmentedColormap.from_list("grad_cmap", [c1, "white", c2])
            gradient = np.linspace(0, 1, 100).reshape(1, -1)  # 横向渐变
            # 计算渐变矩形位置:跟bar完全对齐
            extent = (float(x - width / 2), float(x + width / 2), 0, h)
            # 叠加渐变矩形(imshow)
            ax.imshow(gradient, aspect="auto", cmap=cmap, extent=extent, zorder=0)
    else:
        ax.bar(
            x_positions,
            means,
            width=width,
            color=colors,
            alpha=color_alpha,
            edgecolor=edgecolor,
        )

    ax.errorbar(
        x_positions,
        means,
        error_values,
        fmt="none",
        linewidth=1,
        capsize=3,
        color="black",
    )

    # 绘制散点
    for i, d in enumerate(data):
        if dots_color is None:
            _add_scatter(ax, scatter_positions[i], d, ["gray"] * len(d), dots_size)
        else:
            _add_scatter(ax, scatter_positions[i], d, dots_color[i], dots_size)

    # 美化
    ax.spines[["top", "right"]].set_visible(False)
    ax.set_title(
        title_name,
        fontsize=title_fontsize,
        pad=float(title_pad),
    )
    # x轴
    ax.set_xlim(np.min(x_positions) - 0.5, np.max(x_positions) + 0.5)
    ax.set_xlabel(x_label_name, fontsize=x_label_fontsize)
    ax.set_xticks(x_positions)
    ax.set_xticklabels(
        labels_name,
        fontsize=x_tick_fontsize,
        rotation=x_tick_rotation,
        ha=x_label_ha,
        rotation_mode="anchor",
    )
    # y轴
    ax.tick_params(
        axis="y",
        labelsize=y_tick_fontsize,
        rotation=y_tick_rotation,
    )
    ax.set_ylabel(y_label_name, fontsize=y_label_fontsize)
    all_values = np.concatenate([np.asarray(x) for x in data]).ravel()
    _set_yaxis(
        ax,
        all_values,
        y_lim=y_lim,
        ax_bottom_is_0=ax_bottom_is_0,
        y_max_tick_is_1=y_max_tick_is_1,
        math_text=math_text,
        one_decimal_place=one_decimal_place,
        percentage=percentage,
    )

    # 添加统计显著性标记
    if statistic:
        _statistics(
            data,
            test_method,
            p_list,
            popmean,
            ax,
            all_values,
            statistical_line_color,
            asterisk_fontsize,
            asterisk_color,
        )
    return ax

plot_one_group_violin_figure

plot_one_group_violin_figure(data, ax=None, labels_name=None, width=0.8, colors=None, color_alpha=1, gradient_color=False, colors_start=None, colors_end=None, show_dots=False, dots_size=35, title_name='', title_fontsize=12, title_pad=10, x_label_name='', x_label_ha='center', x_label_fontsize=10, x_tick_fontsize=8, x_tick_rotation=0, y_label_name='', y_label_fontsize=10, y_tick_fontsize=8, y_tick_rotation=0, statistic=False, test_method=['ttest_ind'], popmean=0, p_list=None, statistical_line_color='0.5', asterisk_fontsize=10, asterisk_color='k', y_lim=None, ax_bottom_is_0=False, y_max_tick_is_1=False, math_text=True, one_decimal_place=False, percentage=False)

绘制单组小提琴图,可选散点叠加、渐变填色和统计显著性标注。

Parameters:

Name Type Description Default
data Sequence[list[float] | NDArray[float64]]

输入数据,可以是二维numpy数组或嵌套序列,每个子序列代表一个小提琴的数据点

required
ax Axes | None

matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.

None
labels_name list[str] | None

小提琴图的标签名称列表. Defaults to None.

None
width Num

小提琴图的宽度. Defaults to 0.8.

0.8
colors list[str] | None

小提琴图的颜色列表. Defaults to None.

None
color_alpha Num

小提琴图颜色的透明度. Defaults to 1.

1
gradient_color bool

是否使用渐变颜色填充小提琴图. Defaults to False.

False
colors_start list[str] | None

渐变色的起始颜色列表. Defaults to None.

None
colors_end list[str] | None

渐变色的结束颜色列表. Defaults to None.

None
show_dots bool

是否显示散点. Defaults to False.

False
dots_size Num

散点的大小. Defaults to 35.

35
title_name str

图表标题. Defaults to "".

''
title_fontsize Num

标题字体大小. Defaults to 12.

12
title_pad Num

标题与图表的间距. Defaults to 10.

10
x_label_name str

X轴标签名称. Defaults to "".

''
x_label_ha str

X轴标签的水平对齐方式. Defaults to "center".

'center'
x_label_fontsize Num

X轴标签字体大小. Defaults to 10.

10
x_tick_fontsize Num

X轴刻度字体大小. Defaults to 8.

8
x_tick_rotation Num

X轴刻度旋转角度. Defaults to 0.

0
y_label_name str

Y轴标签名称. Defaults to "".

''
y_label_fontsize Num

Y轴标签字体大小. Defaults to 10.

10
y_tick_fontsize Num

Y轴刻度字体大小. Defaults to 8.

8
y_tick_rotation Num

Y轴刻度旋转角度. Defaults to 0.

0
statistic bool

是否进行统计显著性分析. Defaults to False.

False
test_method list[str]

统计检验方法列表. Defaults to ["ttest_ind"].

['ttest_ind']
popmean Num

单样本t检验的假设均值. Defaults to 0.

0
p_list list[float] | None

预计算的p值列表,用于显著性标记. Defaults to None.

None
statistical_line_color str

显著性标记线的颜色. Defaults to "0.5".

'0.5'
asterisk_fontsize Num

显著性星号的字体大小. Defaults to 10.

10
asterisk_color str

显著性星号的颜色. Defaults to "k".

'k'
y_lim list[Num] | tuple[Num, Num] | None

Y轴的范围限制. Defaults to None.

None
ax_bottom_is_0 bool

Y轴是否从0开始. Defaults to False.

False
y_max_tick_is_1 bool

Y轴最大刻度是否限制为1. Defaults to False.

False
math_text bool

是否将Y轴显示为科学计数法格式. Defaults to True.

True
one_decimal_place bool

Y轴刻度是否只保留一位小数. Defaults to False.

False
percentage bool

是否将Y轴显示为百分比格式. Defaults to False.

False

Raises:

Type Description
ValueError

当data数据格式无效时抛出

Returns:

Type Description
Axes | None

Axes | None: 返回matplotlib的坐标轴对象或None

Source code in src/plotfig/bar.py
def plot_one_group_violin_figure(
    data: Sequence[list[float] | NDArray[np.float64]],
    ax: Axes | None = None,
    labels_name: list[str] | None = None,
    width: Num = 0.8,
    colors: list[str] | None = None,
    color_alpha: Num = 1,
    gradient_color: bool = False,
    colors_start: list[str] | None = None,
    colors_end: list[str] | None = None,
    show_dots: bool = False,
    dots_size: Num = 35,
    title_name: str = "",
    title_fontsize: Num = 12,
    title_pad: Num = 10,
    x_label_name: str = "",
    x_label_ha: str = "center",
    x_label_fontsize: Num = 10,
    x_tick_fontsize: Num = 8,
    x_tick_rotation: Num = 0,
    y_label_name: str = "",
    y_label_fontsize: Num = 10,
    y_tick_fontsize: Num = 8,
    y_tick_rotation: Num = 0,
    statistic: bool = False,
    test_method: list[str] = ["ttest_ind"],
    popmean: Num = 0,
    p_list: list[float] | None = None,
    statistical_line_color: str = "0.5",
    asterisk_fontsize: Num = 10,
    asterisk_color: str = "k",
    y_lim: list[Num] | tuple[Num, Num] | None = None,
    ax_bottom_is_0: bool = False,
    y_max_tick_is_1: bool = False,
    math_text: bool = True,
    one_decimal_place: bool = False,
    percentage: bool = False,
) -> Axes | None:
    """绘制单组小提琴图,可选散点叠加、渐变填色和统计显著性标注。

    Args:
        data (Sequence[list[float] | NDArray[np.float64]]):
            输入数据,可以是二维numpy数组或嵌套序列,每个子序列代表一个小提琴的数据点
        ax (Axes | None, optional):
            matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.
        labels_name (list[str] | None, optional):
            小提琴图的标签名称列表. Defaults to None.
        width (Num, optional):
            小提琴图的宽度. Defaults to 0.8.
        colors (list[str] | None, optional):
            小提琴图的颜色列表. Defaults to None.
        color_alpha (Num, optional):
            小提琴图颜色的透明度. Defaults to 1.
        gradient_color (bool, optional):
            是否使用渐变颜色填充小提琴图. Defaults to False.
        colors_start (list[str] | None, optional):
            渐变色的起始颜色列表. Defaults to None.
        colors_end (list[str] | None, optional):
            渐变色的结束颜色列表. Defaults to None.
        show_dots (bool, optional):
            是否显示散点. Defaults to False.
        dots_size (Num, optional):
            散点的大小. Defaults to 35.
        title_name (str, optional):
            图表标题. Defaults to "".
        title_fontsize (Num, optional):
            标题字体大小. Defaults to 12.
        title_pad (Num, optional):
            标题与图表的间距. Defaults to 10.
        x_label_name (str, optional):
            X轴标签名称. Defaults to "".
        x_label_ha (str, optional):
            X轴标签的水平对齐方式. Defaults to "center".
        x_label_fontsize (Num, optional):
            X轴标签字体大小. Defaults to 10.
        x_tick_fontsize (Num, optional):
            X轴刻度字体大小. Defaults to 8.
        x_tick_rotation (Num, optional):
            X轴刻度旋转角度. Defaults to 0.
        y_label_name (str, optional):
            Y轴标签名称. Defaults to "".
        y_label_fontsize (Num, optional):
            Y轴标签字体大小. Defaults to 10.
        y_tick_fontsize (Num, optional):
            Y轴刻度字体大小. Defaults to 8.
        y_tick_rotation (Num, optional):
            Y轴刻度旋转角度. Defaults to 0.
        statistic (bool, optional):
            是否进行统计显著性分析. Defaults to False.
        test_method (list[str], optional):
            统计检验方法列表. Defaults to ["ttest_ind"].
        popmean (Num, optional):
            单样本t检验的假设均值. Defaults to 0.
        p_list (list[float] | None, optional):
            预计算的p值列表,用于显著性标记. Defaults to None.
        statistical_line_color (str, optional):
            显著性标记线的颜色. Defaults to "0.5".
        asterisk_fontsize (Num, optional):
            显著性星号的字体大小. Defaults to 10.
        asterisk_color (str, optional):
            显著性星号的颜色. Defaults to "k".
        y_lim (list[Num] | tuple[Num, Num] | None, optional):
            Y轴的范围限制. Defaults to None.
        ax_bottom_is_0 (bool, optional):
            Y轴是否从0开始. Defaults to False.
        y_max_tick_is_1 (bool, optional):
            Y轴最大刻度是否限制为1. Defaults to False.
        math_text (bool, optional):
            是否将Y轴显示为科学计数法格式. Defaults to True.
        one_decimal_place (bool, optional):
            Y轴刻度是否只保留一位小数. Defaults to False.
        percentage (bool, optional):
            是否将Y轴显示为百分比格式. Defaults to False.

    Raises:
        ValueError: 当data数据格式无效时抛出

    Returns:
        Axes | None: 返回matplotlib的坐标轴对象或None
    """
    # 处理None值
    if not _is_valid_data(data):
        raise ValueError("无效的 data")
    ax = ax or plt.gca()
    labels_name = labels_name or [str(i) for i in range(len(data))]
    colors = colors or ["gray"] * len(data)
    # 统一参数型
    width = float(width)
    color_alpha = float(color_alpha)
    dots_size = float(dots_size)
    title_fontsize = float(title_fontsize)
    title_pad = float(title_pad)
    x_label_fontsize = float(x_label_fontsize)
    x_tick_fontsize = float(x_tick_fontsize)
    x_tick_rotation = float(x_tick_rotation)
    y_label_fontsize = float(y_label_fontsize)
    y_tick_fontsize = float(y_tick_fontsize)
    y_tick_rotation = float(y_tick_rotation)
    popmean = float(popmean)
    asterisk_fontsize = float(asterisk_fontsize)

    def _draw_gradient_violin(ax, data, pos, width, c1, c2, color_alpha):
        # KDE估计
        kde = stats.gaussian_kde(data)
        buffer = (max(data) - min(data)) / 5
        y = np.linspace(min(data) - buffer, max(data) + buffer, 300)
        ymax = max(data) + buffer
        ymin = min(data) - buffer
        density = kde(y)
        density = density / density.max() * (width / 2)  # 控制violin宽度
        # violin左右边界
        x_left = pos - density
        x_right = pos + density
        # 组合封闭边界
        verts = np.concatenate(
            [np.stack([x_left, y], axis=1), np.stack([x_right[::-1], y[::-1]], axis=1)]
        )
        # 构建渐变图像
        grad_width = 200
        grad_height = 300
        gradient = np.linspace(0, 1, grad_width)
        if c1 == c2:
            rgba = to_rgba(c1, alpha=color_alpha)
            cmap = LinearSegmentedColormap.from_list("cmap", [rgba, rgba])
            gradient_rgb = plt.get_cmap(cmap)(gradient)
        else:
            cmap = LinearSegmentedColormap.from_list("cmap", [c1, "white", c2])
            gradient_rgb = plt.get_cmap(cmap)(gradient)[..., :3]
        gradient_img = np.tile(gradient_rgb, (grad_height, 1, 1))
        # 显示图像并裁剪成violin形状
        im = ax.imshow(
            gradient_img,
            extent=[pos - width / 2, pos + width / 2, y.min(), y.max()],
            origin="lower",
            aspect="auto",
            zorder=1,
        )
        # 添加边界线并作为clip
        poly = Polygon(
            verts,
            closed=True,
            facecolor="none",
            edgecolor="black",
            linewidth=1.2,
            zorder=2,
        )
        ax.add_patch(poly)
        im.set_clip_path(poly)
        # 添加 box 元素
        q1 = np.percentile(data, 25)
        q3 = np.percentile(data, 75)
        median = np.median(data)
        # 添加 IQR box(黑色矩形)
        ax.add_patch(
            Rectangle(
                (pos - width / 16, q1),  # 左下角坐标
                float(width / 8),  # 宽度
                q3 - q1,  # 高度
                facecolor="black",
                alpha=0.7,
            )
        )
        # 添加白色中位数点
        ax.plot(pos, median, "o", color="white", markersize=5, zorder=3)
        return ymax, ymin

    ymax_lst, ymin_lst = [], []
    for i, d in enumerate(data):
        if gradient_color:
            if colors_start is None:
                colors_start = ["#e38a48"] * len(data)
            if colors_end is None:  # 默认颜色
                colors_end = ["#4573a5"] * len(data)
            c1 = colors_start[i]
            c2 = colors_end[i]
        else:
            c1 = c2 = colors[i]
        ymax, ymin = _draw_gradient_violin(ax, d, i, width, c1, c2, color_alpha)

        ymax_lst.append(ymax)
        ymin_lst.append(ymin)
    ymax = max(ymax_lst)
    ymin = min(ymin_lst)

    # 绘制散点(复用现有函数)
    if show_dots:
        scatter_positions = [RNG.normal(i, 0.1, len(d)) for i, d in enumerate(data)]
        for i, d in enumerate(data):
            _add_scatter(ax, scatter_positions[i], d, colors[i], dots_size)

    # 美化
    ax.spines[["top", "right"]].set_visible(False)
    ax.set_title(title_name, fontsize=title_fontsize, pad=title_pad)
    # x轴
    ax.set_xlim(-0.5, len(data) - 0.5)
    ax.set_xlabel(x_label_name, fontsize=x_label_fontsize)
    ax.set_xticks(np.arange(len(data)))
    ax.set_xticklabels(
        labels_name,
        fontsize=x_tick_fontsize,
        rotation=x_tick_rotation,
        ha=x_label_ha,
        rotation_mode="anchor",
    )
    # y轴
    ax.tick_params(
        axis="y",
        labelsize=y_tick_fontsize,
        rotation=y_tick_rotation,
    )
    ax.set_ylabel(y_label_name, fontsize=y_label_fontsize)
    all_values = [ymin, ymax]
    _set_yaxis(
        ax,
        all_values,
        y_lim=y_lim,
        ax_bottom_is_0=ax_bottom_is_0,
        y_max_tick_is_1=y_max_tick_is_1,
        math_text=math_text,
        one_decimal_place=one_decimal_place,
        percentage=percentage,
    )

    # 添加统计标记(复用现有函数)
    if statistic:
        _statistics(
            data,
            test_method,
            p_list,
            popmean,
            ax,
            all_values,
            statistical_line_color,
            asterisk_fontsize,
            asterisk_color,
        )

    return ax

plot_multi_group_bar_figure

plot_multi_group_bar_figure(data, ax=None, group_labels=None, bar_labels=None, bar_width=0.2, bar_gap=0.1, bar_color=None, errorbar_type='sd', dots_color='gray', dots_size=35, legend=True, legend_position=(1.2, 1), title_name='', title_fontsize=12, title_pad=10, x_label_name='', x_label_ha='center', x_label_fontsize=10, x_tick_fontsize=8, x_tick_rotation=0, y_label_name='', y_label_fontsize=10, y_tick_fontsize=8, y_tick_rotation=0, statistic=False, test_method='external', p_list=None, line_color='0.5', asterisk_fontsize=10, asterisk_color='k', y_lim=None, ax_bottom_is_0=False, y_max_tick_is_1=False, math_text=True, one_decimal_place=False, percentage=False)

绘制多组柱状图,包含散点、误差条、显著性标注和图例等。

Parameters:

Name Type Description Default
data DataType

输入数据,可以是三维numpy数组、二维numpy数组列表或嵌套序列

required
ax Axes | None

matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.

None
group_labels list[str] | None

组标签名称列表. Defaults to None.

None
bar_labels list[str] | None

柱状图标签名称列表. Defaults to None.

None
bar_width Num

柱状图的宽度. Defaults to 0.2.

0.2
bar_gap Num

柱状图之间的间隔. Defaults to 0.1.

0.1
bar_color list[str] | None

柱状图的颜色列表. Defaults to None.

None
errorbar_type str

误差条类型,可选 "sd"(标准差) 或 "se"(标准误). Defaults to "sd".

'sd'
dots_color str

散点的颜色. Defaults to "gray".

'gray'
dots_size int

散点的大小. Defaults to 35.

35
legend bool

是否显示图例. Defaults to True.

True
legend_position tuple[Num, Num]

图例位置坐标. Defaults to (1.2, 1).

(1.2, 1)
title_name str

图表标题. Defaults to "".

''
title_fontsize int

标题字体大小. Defaults to 12.

12
title_pad int

标题与图表的间距. Defaults to 10.

10
x_label_name str

X轴标签名称. Defaults to "".

''
x_label_ha str

X轴标签的水平对齐方式. Defaults to "center".

'center'
x_label_fontsize int

X轴标签字体大小. Defaults to 10.

10
x_tick_fontsize int

X轴刻度字体大小. Defaults to 8.

8
x_tick_rotation int

X轴刻度旋转角度. Defaults to 0.

0
y_label_name str

Y轴标签名称. Defaults to "".

''
y_label_fontsize int

Y轴标签字体大小. Defaults to 10.

10
y_tick_fontsize int

Y轴刻度字体大小. Defaults to 8.

8
y_tick_rotation int

Y轴刻度旋转角度. Defaults to 0.

0
statistic bool

是否进行统计显著性分析. Defaults to False.

False
test_method str

统计检验方法,目前仅支持"external". Defaults to "external".

'external'
p_list list[list[Num]] | None

预计算的p值列表,用于显著性标记. Defaults to None.

None
line_color str

显著性标记线的颜色. Defaults to "0.5".

'0.5'
asterisk_fontsize int

显著性星号的字体大小. Defaults to 10.

10
asterisk_color str

显著性星号的颜色. Defaults to "k".

'k'
y_lim list[Num] | tuple[Num, Num] | None

Y轴的范围限制. Defaults to None.

None
ax_bottom_is_0 bool

Y轴是否从0开始. Defaults to False.

False
y_max_tick_is_1 bool

Y轴最大刻度是否限制为1. Defaults to False.

False
math_text bool

是否将Y轴显示为科学计数法格式. Defaults to True.

True
one_decimal_place bool

Y轴刻度是否只保留一位小数. Defaults to False.

False
percentage bool

是否将Y轴显示为百分比格式. Defaults to False.

False

Raises:

Type Description
ValueError

当data数据格式无效时抛出

ValueError

当test_method不是"external"时抛出(多组数据统计测试方法暂时仅支持external方法)

Returns:

Name Type Description
Axes Axes

返回matplotlib的坐标轴对象

Source code in src/plotfig/bar.py
def plot_multi_group_bar_figure(
    data: DataType,
    ax: Axes | None = None,
    group_labels: list[str] | None = None,
    bar_labels: list[str] | None = None,
    bar_width: Num = 0.2,
    bar_gap: Num = 0.1,
    bar_color: list[str] | None = None,
    errorbar_type: str = "sd",
    dots_color: str = "gray",
    dots_size: int = 35,
    legend: bool = True,
    legend_position: tuple[Num, Num] = (1.2, 1),
    title_name: str = "",
    title_fontsize=12,
    title_pad=10,
    x_label_name: str = "",
    x_label_ha="center",
    x_label_fontsize=10,
    x_tick_fontsize=8,
    x_tick_rotation=0,
    y_label_name: str = "",
    y_label_fontsize=10,
    y_tick_fontsize=8,
    y_tick_rotation=0,
    statistic: bool = False,
    test_method: str = "external",
    p_list: list[list[Num]] | None = None,
    line_color="0.5",
    asterisk_fontsize=10,
    asterisk_color="k",
    y_lim: list[Num] | tuple[Num, Num] | None = None,
    ax_bottom_is_0: bool = False,
    y_max_tick_is_1: bool = False,
    math_text: bool = True,
    one_decimal_place: bool = False,
    percentage: bool = False,
) -> Axes:
    """绘制多组柱状图,包含散点、误差条、显著性标注和图例等。

    Args:
        data (DataType):
            输入数据,可以是三维numpy数组、二维numpy数组列表或嵌套序列
        ax (Axes | None, optional):
            matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.
        group_labels (list[str] | None, optional):
            组标签名称列表. Defaults to None.
        bar_labels (list[str] | None, optional):
            柱状图标签名称列表. Defaults to None.
        bar_width (Num, optional):
            柱状图的宽度. Defaults to 0.2.
        bar_gap (Num, optional):
            柱状图之间的间隔. Defaults to 0.1.
        bar_color (list[str] | None, optional):
            柱状图的颜色列表. Defaults to None.
        errorbar_type (str, optional):
            误差条类型,可选 "sd"(标准差) 或 "se"(标准误). Defaults to "sd".
        dots_color (str, optional):
            散点的颜色. Defaults to "gray".
        dots_size (int, optional):
            散点的大小. Defaults to 35.
        legend (bool, optional):
            是否显示图例. Defaults to True.
        legend_position (tuple[Num, Num], optional):
            图例位置坐标. Defaults to (1.2, 1).
        title_name (str, optional):
            图表标题. Defaults to "".
        title_fontsize (int, optional):
            标题字体大小. Defaults to 12.
        title_pad (int, optional):
            标题与图表的间距. Defaults to 10.
        x_label_name (str, optional):
            X轴标签名称. Defaults to "".
        x_label_ha (str, optional):
            X轴标签的水平对齐方式. Defaults to "center".
        x_label_fontsize (int, optional):
            X轴标签字体大小. Defaults to 10.
        x_tick_fontsize (int, optional):
            X轴刻度字体大小. Defaults to 8.
        x_tick_rotation (int, optional):
            X轴刻度旋转角度. Defaults to 0.
        y_label_name (str, optional):
            Y轴标签名称. Defaults to "".
        y_label_fontsize (int, optional):
            Y轴标签字体大小. Defaults to 10.
        y_tick_fontsize (int, optional):
            Y轴刻度字体大小. Defaults to 8.
        y_tick_rotation (int, optional):
            Y轴刻度旋转角度. Defaults to 0.
        statistic (bool, optional):
            是否进行统计显著性分析. Defaults to False.
        test_method (str, optional):
            统计检验方法,目前仅支持"external". Defaults to "external".
        p_list (list[list[Num]] | None, optional):
            预计算的p值列表,用于显著性标记. Defaults to None.
        line_color (str, optional):
            显著性标记线的颜色. Defaults to "0.5".
        asterisk_fontsize (int, optional):
            显著性星号的字体大小. Defaults to 10.
        asterisk_color (str, optional):
            显著性星号的颜色. Defaults to "k".
        y_lim (list[Num] | tuple[Num, Num] | None, optional):
            Y轴的范围限制. Defaults to None.
        ax_bottom_is_0 (bool, optional):
            Y轴是否从0开始. Defaults to False.
        y_max_tick_is_1 (bool, optional):
            Y轴最大刻度是否限制为1. Defaults to False.
        math_text (bool, optional):
            是否将Y轴显示为科学计数法格式. Defaults to True.
        one_decimal_place (bool, optional):
            Y轴刻度是否只保留一位小数. Defaults to False.
        percentage (bool, optional):
            是否将Y轴显示为百分比格式. Defaults to False.

    Raises:
        ValueError: 当data数据格式无效时抛出
        ValueError: 当test_method不是"external"时抛出(多组数据统计测试方法暂时仅支持external方法)

    Returns:
        Axes: 返回matplotlib的坐标轴对象
    """

    def _is_valid_data_for_multi_group(data):
        if not data.any():
            raise ValueError("data 不能为空")
        NumberTypes = (int, float, np.integer, np.floating)
        # 1) 3D ndarray
        if isinstance(data, np.ndarray):
            return data.ndim == 3
        # 必须是外层序列
        if not isinstance(data, (list, tuple)):
            return False
        # 2) 平铺的 list,其中每个元素都是 2D ndarray
        if all(isinstance(x, np.ndarray) and x.ndim == 2 for x in data):
            return True
        # 3) 外层是 groups:每个 group 是序列,group 内的 bar 要么 1D ndarray 要么数字序列
        for group in data:
            if not isinstance(group, (list, tuple)):
                return False
            for bar in group:
                if isinstance(bar, np.ndarray):
                    if bar.ndim != 1:
                        return False
                elif isinstance(bar, (list, tuple)):
                    if not all(isinstance(v, NumberTypes) for v in bar):
                        return False
                else:
                    return False
        return True

    if not _is_valid_data_for_multi_group(data):
        raise ValueError("无效的 data")

    ax = ax or plt.gca()
    group_labels = group_labels or [f"Group {i + 1}" for i in range(len(data))]
    n_groups = len(data)

    # 把所有子列表展开成一个大列表
    all_values = [x for sublist1 in data for sublist2 in sublist1 for x in sublist2]

    x_positions_all = []
    for index_group, group_data in enumerate(data):
        n_bars = len(group_data)
        if bar_labels is None:
            bar_labels = [f"Bar {i + 1}" for i in range(n_bars)]
        if bar_color is None:
            bar_color = ["gray"] * n_bars

        x_positions = (
            np.arange(n_bars) * (bar_width + bar_gap)
            + bar_width / 2
            + index_group
            - (n_bars * bar_width + (n_bars - 1) * bar_gap) / 2
        )
        x_positions_all.append(x_positions)

        # 计算均值、标准差、标准误
        means = [_compute_summary(group_data[i])[0] for i in range(n_bars)]
        sds = [_compute_summary(group_data[i])[1] for i in range(n_bars)]
        ses = [_compute_summary(group_data[i])[2] for i in range(n_bars)]
        if errorbar_type == "sd":
            error_values = sds
        elif errorbar_type == "se":
            error_values = ses
        else:
            raise ValueError("errorbar_type 只能是 'sd' 或者 'se'")
        # 绘制柱子
        bars = ax.bar(
            x_positions, means, width=bar_width, color=bar_color, alpha=1, edgecolor="k"
        )
        ax.errorbar(
            x_positions,
            means,
            error_values,
            fmt="none",
            linewidth=1,
            capsize=3,
            color="black",
        )
        # 绘制散点
        for index_bar, dot in enumerate(group_data):
            dot_x_pos = RNG.normal(
                x_positions[index_bar], scale=bar_width / 7, size=len(dot)
            )
            _add_scatter(ax, dot_x_pos, dot, dots_color, dots_size=dots_size)
    if legend:
        ax.legend(bars, bar_labels, bbox_to_anchor=legend_position)

    # 美化
    ax.spines[["top", "right"]].set_visible(False)
    ax.set_title(
        title_name,
        fontsize=title_fontsize,
        pad=title_pad,
    )
    # x轴
    ax.set_xlabel(x_label_name, fontsize=x_label_fontsize)
    ax.set_xticks(np.arange(n_groups))
    ax.set_xticklabels(
        group_labels,
        ha=x_label_ha,
        rotation_mode="anchor",
        fontsize=x_tick_fontsize,
        rotation=x_tick_rotation,
    )
    # y轴
    ax.tick_params(
        axis="y",
        labelsize=y_tick_fontsize,
        rotation=y_tick_rotation,
    )
    ax.set_ylabel(y_label_name, fontsize=y_label_fontsize)
    _set_yaxis(
        ax,
        all_values,
        y_lim,
        ax_bottom_is_0,
        y_max_tick_is_1,
        math_text,
        one_decimal_place,
        percentage,
    )

    # 添加统计显著性标记
    if statistic:
        for index_group, group_data in enumerate(data):
            x_positions = x_positions_all[index_group]
            comparisons = []
            idx = 0
            for i in range(len(group_data)):
                for j in range(i + 1, len(group_data)):
                    if test_method == "external":
                        if p_list is None:
                            raise ValueError("p_list不能为空")
                        p = p_list[index_group][idx]
                        idx += 1
                    else:
                        raise ValueError("多组数据统计测试方法暂时仅支持 external方法")
                    if p <= 0.05:
                        comparisons.append((x_positions[i], x_positions[j], p))
            y_max = ax.get_ylim()[1]
            interval = (y_max - np.max(all_values)) / (len(comparisons) + 1)
            _annotate_significance(
                ax,
                comparisons,
                np.max(all_values),
                interval,
                line_color=line_color,
                star_offset=interval / 5,
                fontsize=asterisk_fontsize,
                color=asterisk_color,
            )

    return ax

plotfig.correlation

plot_correlation_figure

plot_correlation_figure(data1, data2, ax=None, stats_method='spearman', ci=False, dots_color='steelblue', dots_size=1, line_color='r', title_name='', title_fontsize=10, title_pad=10, x_label_name='', x_label_fontsize=10, x_tick_fontsize=10, x_tick_rotation=0, x_major_locator=None, x_max_tick_to_value=None, x_format='normal', y_label_name='', y_label_fontsize=10, y_tick_fontsize=10, y_tick_rotation=0, y_major_locator=None, y_max_tick_to_value=None, y_format='normal', asterisk_fontsize=10, show_p_value=False, hexbin=False, hexbin_cmap=None, hexbin_gridsize=50)

绘制两个数据集之间的相关性图,支持线性回归、置信区间和统计方法(Spearman 或 Pearson)。

Parameters:

Name Type Description Default
data1 list[Num] | ndarray

第一个数据集,可以是整数或浮点数列表或数组。

required
data2 list[Num] | ndarray

第二个数据集,可以是整数或浮点数列表或数组。

required
ax Axes | None

matplotlib 的 Axes 对象,用于绘图。默认为 None,使用当前 Axes。

None
stats_method str

相关性统计方法,支持 "spearman" 和 "pearson"。默认为 "spearman"。

'spearman'
ci bool

是否绘制置信区间带。默认为 False。

False
dots_color str

散点的颜色。默认为 "steelblue"。

'steelblue'
dots_size int | float

散点的大小。默认为 1。

1
line_color str

回归线的颜色。默认为 "r"(红色)。

'r'
title_name str

图形标题。默认为空字符串。

''
title_fontsize int

标题字体大小。默认为 10。

10
title_pad int

标题与图形之间的间距。默认为 10。

10
x_label_name str

X 轴标签名称。默认为空字符串。

''
x_label_fontsize int

X 轴标签字体大小。默认为 10。

10
x_tick_fontsize int

X 轴刻度标签字体大小。默认为 10。

10
x_tick_rotation int

X 轴刻度标签旋转角度。默认为 0。

0
x_major_locator float | None

设置 X 轴主刻度间隔。默认为 None。

None
x_max_tick_to_value float | None

设置 X 轴最大显示刻度值。默认为 None。

None
x_format str

X 轴格式化方式,支持 "normal", "sci", "1f", "percent"。默认为 "normal"。

'normal'
y_label_name str

Y 轴标签名称。默认为空字符串。

''
y_label_fontsize int

Y 轴标签字体大小。默认为 10。

10
y_tick_fontsize int

Y 轴刻度标签字体大小。默认为 10。

10
y_tick_rotation int

Y 轴刻度标签旋转角度。默认为 0。

0
y_major_locator float | None

设置 Y 轴主刻度间隔。默认为 None。

None
y_max_tick_to_value float | None

设置 Y 轴最大显示刻度值。默认为 None。

None
y_format str

Y 轴格式化方式,支持 "normal", "sci", "1f", "percent"。默认为 "normal"。

'normal'
asterisk_fontsize int

显著性星号字体大小。默认为 10。

10
show_p_value bool

是否显示 p 值。默认为 True。

False

Returns:

Type Description
None

None

Source code in src/plotfig/correlation.py
def plot_correlation_figure(
    data1: list[Num] | np.ndarray,
    data2: list[Num] | np.ndarray,
    ax: plt.Axes | None = None,
    stats_method: str = "spearman",
    ci: bool = False,
    dots_color: str = "steelblue",
    dots_size: int | float = 1,
    line_color: str = "r",
    title_name: str = "",
    title_fontsize: int = 10,
    title_pad: int = 10,
    x_label_name: str = "",
    x_label_fontsize: int = 10,
    x_tick_fontsize: int = 10,
    x_tick_rotation: int = 0,
    x_major_locator: float | None = None,
    x_max_tick_to_value: float | None = None,
    x_format: str = "normal",  # 支持 "normal", "sci", "1f", "percent"
    y_label_name: str = "",
    y_label_fontsize: int = 10,
    y_tick_fontsize: int = 10,
    y_tick_rotation: int = 0,
    y_major_locator: float | None = None,
    y_max_tick_to_value: float | None = None,
    y_format: str = "normal",  # 支持 "normal", "sci", "1f", "percent"
    asterisk_fontsize: int = 10,
    show_p_value: bool = False,
    hexbin: bool = False,
    hexbin_cmap: bool = None,
    hexbin_gridsize:int = 50,
) -> None:
    """
    绘制两个数据集之间的相关性图,支持线性回归、置信区间和统计方法(Spearman 或 Pearson)。

    Args:
        data1 (list[Num] | np.ndarray): 第一个数据集,可以是整数或浮点数列表或数组。
        data2 (list[Num] | np.ndarray): 第二个数据集,可以是整数或浮点数列表或数组。
        ax (plt.Axes | None, optional): matplotlib 的 Axes 对象,用于绘图。默认为 None,使用当前 Axes。
        stats_method (str, optional): 相关性统计方法,支持 "spearman" 和 "pearson"。默认为 "spearman"。
        ci (bool, optional): 是否绘制置信区间带。默认为 False。
        dots_color (str, optional): 散点的颜色。默认为 "steelblue"。
        dots_size (int | float, optional): 散点的大小。默认为 1。
        line_color (str, optional): 回归线的颜色。默认为 "r"(红色)。
        title_name (str, optional): 图形标题。默认为空字符串。
        title_fontsize (int, optional): 标题字体大小。默认为 10。
        title_pad (int, optional): 标题与图形之间的间距。默认为 10。
        x_label_name (str, optional): X 轴标签名称。默认为空字符串。
        x_label_fontsize (int, optional): X 轴标签字体大小。默认为 10。
        x_tick_fontsize (int, optional): X 轴刻度标签字体大小。默认为 10。
        x_tick_rotation (int, optional): X 轴刻度标签旋转角度。默认为 0。
        x_major_locator (float | None, optional): 设置 X 轴主刻度间隔。默认为 None。
        x_max_tick_to_value (float | None, optional): 设置 X 轴最大显示刻度值。默认为 None。
        x_format (str, optional): X 轴格式化方式,支持 "normal", "sci", "1f", "percent"。默认为 "normal"。
        y_label_name (str, optional): Y 轴标签名称。默认为空字符串。
        y_label_fontsize (int, optional): Y 轴标签字体大小。默认为 10。
        y_tick_fontsize (int, optional): Y 轴刻度标签字体大小。默认为 10。
        y_tick_rotation (int, optional): Y 轴刻度标签旋转角度。默认为 0。
        y_major_locator (float | None, optional): 设置 Y 轴主刻度间隔。默认为 None。
        y_max_tick_to_value (float | None, optional): 设置 Y 轴最大显示刻度值。默认为 None。
        y_format (str, optional): Y 轴格式化方式,支持 "normal", "sci", "1f", "percent"。默认为 "normal"。
        asterisk_fontsize (int, optional): 显著性星号字体大小。默认为 10。
        show_p_value (bool, optional): 是否显示 p 值。默认为 True。

    Returns:
        None
    """
    def set_axis(
        ax, axis, label, labelsize, ticksize, rotation, locator, max_tick_value, fmt
    ):
        if axis == "x":
            set_label = ax.set_xlabel
            get_ticks = ax.get_xticks
            set_ticks = ax.set_xticks
            axis_formatter = ax.xaxis.set_major_formatter
            axis_major_locator = ax.xaxis.set_major_locator
        else:
            set_label = ax.set_ylabel
            get_ticks = ax.get_yticks
            set_ticks = ax.set_yticks
            axis_formatter = ax.yaxis.set_major_formatter
            axis_major_locator = ax.yaxis.set_major_locator

        set_label(label, fontsize=labelsize)
        ax.tick_params(axis=axis, which="major", labelsize=ticksize, rotation=rotation)
        if locator is not None:
            axis_major_locator(MultipleLocator(locator))
        if max_tick_value is not None:
            set_ticks([i for i in get_ticks() if i <= max_tick_value])

        if fmt == "sci":
            formatter = ScalarFormatter(useMathText=True)
            formatter.set_powerlimits((-2, 2))
            axis_formatter(formatter)
        elif fmt == "1f":
            axis_formatter(FormatStrFormatter("%.1f"))
        elif fmt == "percent":
            axis_formatter(FuncFormatter(lambda x, pos: f"{x:.0%}"))

    if ax is None:
        ax = plt.gca()

    A = np.asarray(data1)
    B = np.asarray(data2)

    slope, intercept, r_value, p_value, _ = stats.linregress(A, B)
    x_seq = np.linspace(A.min(), A.max(), 100)
    y_pred = slope * x_seq + intercept

    if hexbin:
        if hexbin_cmap is None:
            hexbin_cmap = LinearSegmentedColormap.from_list('custom', ['#ffffff', '#4573a5'])
        hb = ax.hexbin(A, B, gridsize=hexbin_gridsize, cmap=hexbin_cmap)
    else:
        ax.scatter(A, B, c=dots_color, s=dots_size, alpha=0.8)
    ax.plot(x_seq, y_pred, line_color, lw=1)

    if ci:
        n = len(A)
        dof = n - 2
        t_val = stats.t.ppf(0.975, dof)
        x_mean = A.mean()
        residuals = B - (slope * A + intercept)
        s_err = np.sqrt(np.sum(residuals**2) / dof)
        SSxx = np.sum((A - x_mean) ** 2)
        conf_interval = t_val * s_err * np.sqrt(1 / n + (x_seq - x_mean) ** 2 / SSxx)
        ax.fill_between(
            x_seq,
            y_pred - conf_interval,
            y_pred + conf_interval,
            color="salmon",
            alpha=0.3,
        )

    ax.spines[["top", "right"]].set_visible(False)
    ax.set_title(title_name, fontsize=title_fontsize, pad=title_pad)

    set_axis(
        ax,
        "x",
        x_label_name,
        x_label_fontsize,
        x_tick_fontsize,
        x_tick_rotation,
        x_major_locator,
        x_max_tick_to_value,
        x_format,
    )
    set_axis(
        ax,
        "y",
        y_label_name,
        y_label_fontsize,
        y_tick_fontsize,
        y_tick_rotation,
        y_major_locator,
        y_max_tick_to_value,
        y_format,
    )

    # 标注r值或rho值
    if stats_method == "spearman":
        s, p = stats.spearmanr(A, B)
        label = r"$\rho$"
    elif stats_method == "pearson":
        s, p = stats.pearsonr(A, B)
        label = "r"
    else:
        print(f"没有统计方法 {stats_method},请检查拼写。更换为默认的 spearman 方法。")
        s, p = stats.spearmanr(A, B)
        label = r"$\rho$"

    if show_p_value:
        asterisk = f" p={p:.4f}"
    else:
        asterisk = " ***" if p < 0.001 else " **" if p < 0.01 else " *" if p < 0.05 else ""
    x_start, x_end = ax.get_xlim()
    y_start, y_end = ax.get_ylim()
    ax.text(
        x_start + (x_end - x_start) * 0.1,
        y_start + (y_end - y_start) * 0.9,
        f"{label}={s:.3f}{asterisk}",
        va="center",
        fontsize=asterisk_fontsize,
    )
    if hexbin:
        return hb
    return

plotfig.matrix

plot_matrix_figure

plot_matrix_figure(data, ax=None, row_labels_name=None, col_labels_name=None, cmap='bwr', vmin=None, vmax=None, aspect='equal', colorbar=True, colorbar_label_name='', colorbar_pad=0.1, colorbar_label_fontsize=10, colorbar_tick_fontsize=10, colorbar_tick_rotation=0, row_labels_fontsize=10, col_labels_fontsize=10, x_rotation=60, title_name='', title_fontsize=15, title_pad=20, diag_border=False, **imshow_kwargs)

Plot a matrix as a heatmap with optional labels, colorbar, and title.

Parameters:

Name Type Description Default
data ndarray

2D array of shape (N, M) to display as the matrix.

required
ax Axes | None

Matplotlib axes to plot on. If None, uses current axes.

None
row_labels_name Sequence[str] | None

List of labels for the rows.

None
col_labels_name Sequence[str] | None

List of labels for the columns.

None
cmap str

Colormap to use for the matrix.

'bwr'
vmin Num | None

Minimum value for color scaling. Defaults to data.min().

None
vmax Num | None

Maximum value for color scaling. Defaults to data.max().

None
aspect str

Aspect ratio of the plot. Usually "equal" or "auto".

'equal'
colorbar bool

Whether to show a colorbar.

True
colorbar_label_name str

Label for the colorbar.

''
colorbar_pad Num

Padding between the colorbar and the matrix.

0.1
colorbar_label_fontsize Num

Font size of the colorbar label.

10
colorbar_tick_fontsize Num

Font size of the colorbar ticks.

10
colorbar_tick_rotation Num

Rotation angle of the colorbar tick labels.

0
row_labels_fontsize Num

Font size for the row labels.

10
col_labels_fontsize Num

Font size for the column labels.

10
x_rotation Num

Rotation angle for the x-axis (column) labels.

60
title_name Num

Title of the plot.

''
title_fontsize Num

Font size of the title.

15
title_pad Num

Padding above the title.

20
diag_border bool

Whether to draw borders along the diagonal cells.

False
**imshow_kwargs Any

Additional keyword arguments for imshow().

{}

Returns:

Name Type Description
AxesImage AxesImage

The image object created by imshow().

Source code in src/plotfig/matrix.py
def plot_matrix_figure(
    data: np.ndarray,
    ax: Axes | None = None,
    row_labels_name: Sequence[str] | None = None,
    col_labels_name: Sequence[str] | None = None,
    cmap: str = "bwr",
    vmin: Num | None = None,
    vmax: Num | None = None,
    aspect: str = "equal",
    colorbar: bool = True,
    colorbar_label_name: str = "",
    colorbar_pad: Num = 0.1,
    colorbar_label_fontsize: Num = 10,
    colorbar_tick_fontsize: Num = 10,
    colorbar_tick_rotation: Num = 0,
    row_labels_fontsize: Num = 10,
    col_labels_fontsize: Num = 10,
    x_rotation: Num = 60,
    title_name: str = "",
    title_fontsize: Num = 15,
    title_pad: Num = 20,
    diag_border: bool = False,
    **imshow_kwargs: Any,
) -> AxesImage:
    """Plot a matrix as a heatmap with optional labels, colorbar, and title.

    Args:
        data (np.ndarray): 2D array of shape (N, M) to display as the matrix.
        ax (Axes | None): Matplotlib axes to plot on. If None, uses current axes.
        row_labels_name (Sequence[str] | None): List of labels for the rows.
        col_labels_name (Sequence[str] | None): List of labels for the columns.
        cmap (str): Colormap to use for the matrix.
        vmin (Num | None): Minimum value for color scaling. Defaults to data.min().
        vmax (Num | None): Maximum value for color scaling. Defaults to data.max().
        aspect (str): Aspect ratio of the plot. Usually "equal" or "auto".
        colorbar (bool): Whether to show a colorbar.
        colorbar_label_name (str): Label for the colorbar.
        colorbar_pad (Num): Padding between the colorbar and the matrix.
        colorbar_label_fontsize (Num): Font size of the colorbar label.
        colorbar_tick_fontsize (Num): Font size of the colorbar ticks.
        colorbar_tick_rotation (Num): Rotation angle of the colorbar tick labels.
        row_labels_fontsize (Num): Font size for the row labels.
        col_labels_fontsize (Num): Font size for the column labels.
        x_rotation (Num): Rotation angle for the x-axis (column) labels.
        title_name (Num): Title of the plot.
        title_fontsize (Num): Font size of the title.
        title_pad (Num): Padding above the title.
        diag_border (bool): Whether to draw borders along the diagonal cells.
        **imshow_kwargs (Any): Additional keyword arguments for `imshow()`.

    Returns:
        AxesImage: The image object created by `imshow()`.
    """
    ax = ax or plt.gca()
    vmin = vmin if vmin is not None else np.min(data)
    vmax = vmax if vmax is not None else np.max(data)

    im = ax.imshow(
        data, cmap=cmap, vmin=vmin, vmax=vmax, aspect=aspect, **imshow_kwargs
    )
    ax.set_title(title_name, fontsize=title_fontsize, pad=title_pad)
    if diag_border:
        for i in range(data.shape[0]):
            ax.add_patch(
                plt.Rectangle(
                    (i - 0.5, i - 0.5), 1, 1, fill=False, edgecolor="black", lw=0.5
                )
            )

    if col_labels_name is not None:
        ax.set_xticks(np.arange(data.shape[1]))
        ax.set_xticklabels(
            col_labels_name,
            fontsize=col_labels_fontsize,
            rotation=x_rotation,
            ha="right",
            rotation_mode="anchor",
        )

    if row_labels_name is not None:
        ax.set_yticks(np.arange(data.shape[0]))
        ax.set_yticklabels(row_labels_name, fontsize=row_labels_fontsize)

    if colorbar:
        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="5%", pad=colorbar_pad)
        cbar = ax.figure.colorbar(im, cax=cax)
        cbar.ax.set_ylabel(
            colorbar_label_name,
            rotation=-90,
            va="bottom",
            fontsize=colorbar_label_fontsize,
        )
        cbar.ax.tick_params(
            labelsize=colorbar_tick_fontsize, rotation=colorbar_tick_rotation
        )
        # Match colorbar height to the main plot
        ax_pos = ax.get_position()
        cax.set_position(
            [cax.get_position().x0, ax_pos.y0, cax.get_position().width, ax_pos.height]
        )

    return

plotfig.circos

plot_asymmetric_circle_figure

plot_asymmetric_circle_figure(connectome, labels=None, node_colors=None, vmin=None, vmax=None, figsize=(10, 10), labels_fontsize=15, face_color='w', nodeedge_color='w', text_color='k', cmap='bwr', linewidth=1, title_name='', title_fontsize=20, colorbar=False, colorbar_size=0.2, colorbar_fontsize=10, colorbar_pos=(0, 0), manual_colorbar=False, manual_colorbar_pos=(1, 0.4, 0.01, 0.2), manual_cmap='bwr', manual_colorbar_name='', manual_colorbar_label_fontsize=10, manual_colorbar_fontsize=10, manual_colorbar_rotation=-90, manual_colorbar_pad=20, manual_colorbar_draw_border=True, manual_colorbar_tickline=False, manual_colorbar_nticks=False)

绘制类circos连接图

Parameters:

Name Type Description Default
connectome NDArray

连接矩阵.

required
labels list[str] | None

节点名称. Defaults to None.

None
node_colors list[str] | None

节点颜色. Defaults to None.

None
vmin Num | None

最小值. Defaults to None.

None
vmax Num | None

最大值. Defaults to None.

None
figsize Tuple[Num, Num]

图大小. Defaults to (10, 10).

(10, 10)
labels_fontsize Num

节点名字大小. Defaults to 15.

15
face_color str

图背景颜色. Defaults to "w".

'w'
nodeedge_color str

节点轮廓颜色. Defaults to "w".

'w'
text_color str

文本颜色. Defaults to "k".

'k'
cmap str

colorbar颜色. Defaults to "bwr".

'bwr'
linewidth Num

连接线宽度. Defaults to 1.

1
title_name str

图标题名称. Defaults to "".

''
title_fontsize Num

图标题字体大小. Defaults to 20.

20
colorbar bool

是否绘制colorbar. Defaults to False.

False
colorbar_size Num

colorbar大小. Defaults to 0.2.

0.2
colorbar_fontsize Num

colorbar字体大小. Defaults to 10.

10
colorbar_pos Tuple[Num, Num]

colorbar位置. Defaults to (0, 0).

(0, 0)
manual_colorbar bool

高级colorbar. Defaults to False.

False
manual_colorbar_pos Tuple[Num, Num, Num, Num]

高级colorbar位置. Defaults to (1, 0.4, 0.01, 0.2).

(1, 0.4, 0.01, 0.2)
manual_cmap str

高级colorbar cmap. Defaults to "bwr".

'bwr'
manual_colorbar_name str

高级colorbar名字. Defaults to "".

''
manual_colorbar_label_fontsize Num

高级colorbar label字体大小. Defaults to 10.

10
manual_colorbar_fontsize Num

高级colorbar字体大小. Defaults to 10.

10
manual_colorbar_rotation Num

高级colorbar旋转. Defaults to -90.

-90
manual_colorbar_pad Num

高级colorbar标题间隔距离. Defaults to 20.

20
manual_colorbar_draw_border bool

高级colorbar轮廓. Defaults to True.

True
manual_colorbar_tickline bool

高级colorbar tick线. Defaults to False.

False
manual_colorbar_nticks bool

高级colorbar tick数量. Defaults to False.

False

Returns:

Type Description
Figure

plt.Figure: description

Source code in src/plotfig/circos.py
def plot_asymmetric_circle_figure(
    connectome: npt.NDArray,
    labels: list[str] | None = None,
    node_colors: list[str] | None = None,
    vmin: Num | None = None,
    vmax: Num | None = None,
    figsize: Tuple[Num, Num] = (10, 10),
    labels_fontsize: Num = 15,
    face_color: str = "w",
    nodeedge_color: str = "w",
    text_color: str = "k",
    cmap: str = "bwr",
    linewidth: Num = 1,
    title_name: str = "",
    title_fontsize: Num = 20,
    colorbar: bool = False,
    colorbar_size: Num = 0.2,
    colorbar_fontsize: Num = 10,
    colorbar_pos: Tuple[Num, Num] = (0, 0),
    manual_colorbar: bool = False,
    manual_colorbar_pos: Tuple[Num, Num, Num, Num] = (1, 0.4, 0.01, 0.2),
    manual_cmap: str = "bwr",
    manual_colorbar_name: str = "",
    manual_colorbar_label_fontsize: Num = 10,
    manual_colorbar_fontsize: Num = 10,
    manual_colorbar_rotation: Num = -90,
    manual_colorbar_pad: Num = 20,
    manual_colorbar_draw_border: bool = True,
    manual_colorbar_tickline: bool = False,
    manual_colorbar_nticks: bool = False,
) -> plt.Figure:
    """绘制类circos连接图

    Args:
        connectome (npt.NDArray): 连接矩阵.
        labels (list[str] | None, optional): 节点名称. Defaults to None.
        node_colors (list[str] | None, optional): 节点颜色. Defaults to None.
        vmin (Num | None, optional): 最小值. Defaults to None.
        vmax (Num | None, optional): 最大值. Defaults to None.
        figsize (Tuple[Num, Num], optional): 图大小. Defaults to (10, 10).
        labels_fontsize (Num, optional): 节点名字大小. Defaults to 15.
        face_color (str, optional): 图背景颜色. Defaults to "w".
        nodeedge_color (str, optional): 节点轮廓颜色. Defaults to "w".
        text_color (str, optional): 文本颜色. Defaults to "k".
        cmap (str, optional): colorbar颜色. Defaults to "bwr".
        linewidth (Num, optional): 连接线宽度. Defaults to 1.
        title_name (str, optional): 图标题名称. Defaults to "".
        title_fontsize (Num, optional): 图标题字体大小. Defaults to 20.
        colorbar (bool, optional): 是否绘制colorbar. Defaults to False.
        colorbar_size (Num, optional): colorbar大小. Defaults to 0.2.
        colorbar_fontsize (Num, optional): colorbar字体大小. Defaults to 10.
        colorbar_pos (Tuple[Num, Num], optional): colorbar位置. Defaults to (0, 0).
        manual_colorbar (bool, optional): 高级colorbar. Defaults to False.
        manual_colorbar_pos (Tuple[Num, Num, Num, Num], optional): 高级colorbar位置. Defaults to (1, 0.4, 0.01, 0.2).
        manual_cmap (str, optional): 高级colorbar cmap. Defaults to "bwr".
        manual_colorbar_name (str, optional): 高级colorbar名字. Defaults to "".
        manual_colorbar_label_fontsize (Num, optional): 高级colorbar label字体大小. Defaults to 10.
        manual_colorbar_fontsize (Num, optional): 高级colorbar字体大小. Defaults to 10.
        manual_colorbar_rotation (Num, optional): 高级colorbar旋转. Defaults to -90.
        manual_colorbar_pad (Num, optional): 高级colorbar标题间隔距离. Defaults to 20.
        manual_colorbar_draw_border (bool, optional): 高级colorbar轮廓. Defaults to True.
        manual_colorbar_tickline (bool, optional): 高级colorbar tick线. Defaults to False.
        manual_colorbar_nticks (bool, optional): 高级colorbar tick数量. Defaults to False.

    Returns:
        plt.Figure: _description_
    """
    # 设置默认值
    if vmax is None:
        vmax = np.max((np.max(connectome), -np.min(connectome)))
    if vmin is None:
        vmin = np.min((np.min(connectome), -np.max(connectome)))
    count = connectome.shape[0]
    if labels is None:
        labels = [str(i) for i in range(count)]
    if node_colors is None:
        node_colors = ["#ff8f8f"] * count
    node_angles = mne.viz.circular_layout(labels, labels)
    # 画图
    fig, ax = plt.subplots(figsize=figsize, subplot_kw={"polar": True})
    fig.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)
    plot_connectivity_circle(
        connectome,
        labels,
        node_angles=node_angles,
        node_colors=node_colors,
        fontsize_names=labels_fontsize,
        facecolor=face_color,
        node_edgecolor=nodeedge_color,
        textcolor=text_color,
        colormap=cmap,
        vmin=vmin,
        vmax=vmax,
        linewidth=linewidth,
        title=title_name,
        fontsize_title=title_fontsize,
        colorbar=colorbar,
        colorbar_size=colorbar_size,
        colorbar_pos=colorbar_pos,
        fontsize_colorbar=colorbar_fontsize,
        fig=fig,
        ax=ax,
        interactive=False,
        show=False,
    )
    # 如有需要,禁用自动colorbar,手动生成colorbar
    if manual_colorbar:
        # 手动创建colorbar,拥有更多的设置
        cax = fig.add_axes(manual_colorbar_pos)
        norm = plt.Normalize(vmin=vmin, vmax=vmax)
        sm = plt.cm.ScalarMappable(cmap=manual_cmap, norm=norm)
        sm.set_array([])
        cbar = fig.colorbar(sm, cax=cax)
        cbar.outline.set_visible(manual_colorbar_draw_border)
        cbar.ax.set_ylabel(
            manual_colorbar_name,
            fontsize=manual_colorbar_label_fontsize,
            rotation=manual_colorbar_rotation,
            labelpad=manual_colorbar_pad,
        )
        if not manual_colorbar_tickline:
            cbar.ax.tick_params(length=0)  # 不显示竖线
        cbar.ax.yaxis.set_ticks_position("left")
        cbar.ax.tick_params(labelsize=manual_colorbar_fontsize)
        if manual_colorbar_nticks:
            ticks = np.linspace(vmin, vmax, manual_colorbar_nticks)
            cbar.set_ticks(ticks)
    return fig

plot_symmetric_circle_figure

plot_symmetric_circle_figure(connectome, labels=None, node_colors=None, vmin=None, vmax=None, figsize=(10, 10), labels_fontsize=15, face_color='w', nodeedge_color='w', text_color='k', cmap='bwr', linewidth=1, title_name='', title_fontsize=20, colorbar=False, colorbar_size=0.2, colorbar_fontsize=10, colorbar_pos=(0, 0), manual_colorbar=False, manual_colorbar_pos=(1, 0.4, 0.01, 0.2), manual_cmap='bwr', manual_colorbar_name='', manual_colorbar_label_fontsize=10, manual_colorbar_fontsize=10, manual_colorbar_rotation=-90, manual_colorbar_pad=20, manual_colorbar_draw_border=True, manual_colorbar_tickline=False, manual_colorbar_nticks=False)

绘制类circos连接图

Parameters:

Name Type Description Default
connectome NDArray

连接矩阵.

required
labels list[str] | None

节点名称. Defaults to None.

None
node_colors list[str] | None

节点颜色. Defaults to None.

None
vmin Num | None

最小值. Defaults to None.

None
vmax Num | None

最大值. Defaults to None.

None
figsize Tuple[Num, Num]

图大小. Defaults to (10, 10).

(10, 10)
labels_fontsize Num

节点名字大小. Defaults to 15.

15
face_color str

图背景颜色. Defaults to "w".

'w'
nodeedge_color str

节点轮廓颜色. Defaults to "w".

'w'
text_color str

文本颜色. Defaults to "k".

'k'
cmap str

colorbar颜色. Defaults to "bwr".

'bwr'
linewidth Num

连接线宽度. Defaults to 1.

1
title_name str

图标题名称. Defaults to "".

''
title_fontsize Num

图标题字体大小. Defaults to 20.

20
colorbar bool

是否绘制colorbar. Defaults to False.

False
colorbar_size Num

colorbar大小. Defaults to 0.2.

0.2
colorbar_fontsize Num

colorbar字体大小. Defaults to 10.

10
colorbar_pos Tuple[Num, Num]

colorbar位置. Defaults to (0, 0).

(0, 0)
manual_colorbar bool

高级colorbar. Defaults to False.

False
manual_colorbar_pos Tuple[Num, Num, Num, Num]

高级colorbar位置. Defaults to (1, 0.4, 0.01, 0.2).

(1, 0.4, 0.01, 0.2)
manual_cmap str

高级colorbar cmap. Defaults to "bwr".

'bwr'
manual_colorbar_name str

高级colorbar名字. Defaults to "".

''
manual_colorbar_label_fontsize Num

高级colorbar label字体大小. Defaults to 10.

10
manual_colorbar_fontsize Num

高级colorbar字体大小. Defaults to 10.

10
manual_colorbar_rotation Num

高级colorbar旋转. Defaults to -90.

-90
manual_colorbar_pad Num

高级colorbar标题间隔距离. Defaults to 20.

20
manual_colorbar_draw_border bool

高级colorbar轮廓. Defaults to True.

True
manual_colorbar_tickline bool

高级colorbar tick线. Defaults to False.

False
manual_colorbar_nticks bool

高级colorbar tick数量. Defaults to False.

False

Returns:

Type Description
Figure

plt.Figure: description

Source code in src/plotfig/circos.py
def plot_symmetric_circle_figure(
    connectome: npt.NDArray,
    labels: list[str] | None = None,
    node_colors: list[str] | None = None,
    vmin: Num | None = None,
    vmax: Num | None = None,
    figsize: Tuple[Num, Num] = (10, 10),
    labels_fontsize: Num = 15,
    face_color: str = "w",
    nodeedge_color: str = "w",
    text_color: str = "k",
    cmap: str = "bwr",
    linewidth: Num = 1,
    title_name: str = "",
    title_fontsize: Num = 20,
    colorbar: bool = False,
    colorbar_size: Num = 0.2,
    colorbar_fontsize: Num = 10,
    colorbar_pos: Tuple[Num, Num] = (0, 0),
    manual_colorbar: bool = False,
    manual_colorbar_pos: Tuple[Num, Num, Num, Num] = (1, 0.4, 0.01, 0.2),
    manual_cmap: str = "bwr",
    manual_colorbar_name: str = "",
    manual_colorbar_label_fontsize: Num = 10,
    manual_colorbar_fontsize: Num = 10,
    manual_colorbar_rotation: Num = -90,
    manual_colorbar_pad: Num = 20,
    manual_colorbar_draw_border: bool = True,
    manual_colorbar_tickline: bool = False,
    manual_colorbar_nticks: bool = False,
) -> plt.Figure:
    """绘制类circos连接图

    Args:
        connectome (npt.NDArray): 连接矩阵.
        labels (list[str] | None, optional): 节点名称. Defaults to None.
        node_colors (list[str] | None, optional): 节点颜色. Defaults to None.
        vmin (Num | None, optional): 最小值. Defaults to None.
        vmax (Num | None, optional): 最大值. Defaults to None.
        figsize (Tuple[Num, Num], optional): 图大小. Defaults to (10, 10).
        labels_fontsize (Num, optional): 节点名字大小. Defaults to 15.
        face_color (str, optional): 图背景颜色. Defaults to "w".
        nodeedge_color (str, optional): 节点轮廓颜色. Defaults to "w".
        text_color (str, optional): 文本颜色. Defaults to "k".
        cmap (str, optional): colorbar颜色. Defaults to "bwr".
        linewidth (Num, optional): 连接线宽度. Defaults to 1.
        title_name (str, optional): 图标题名称. Defaults to "".
        title_fontsize (Num, optional): 图标题字体大小. Defaults to 20.
        colorbar (bool, optional): 是否绘制colorbar. Defaults to False.
        colorbar_size (Num, optional): colorbar大小. Defaults to 0.2.
        colorbar_fontsize (Num, optional): colorbar字体大小. Defaults to 10.
        colorbar_pos (Tuple[Num, Num], optional): colorbar位置. Defaults to (0, 0).
        manual_colorbar (bool, optional): 高级colorbar. Defaults to False.
        manual_colorbar_pos (Tuple[Num, Num, Num, Num], optional): 高级colorbar位置. Defaults to (1, 0.4, 0.01, 0.2).
        manual_cmap (str, optional): 高级colorbar cmap. Defaults to "bwr".
        manual_colorbar_name (str, optional): 高级colorbar名字. Defaults to "".
        manual_colorbar_label_fontsize (Num, optional): 高级colorbar label字体大小. Defaults to 10.
        manual_colorbar_fontsize (Num, optional): 高级colorbar字体大小. Defaults to 10.
        manual_colorbar_rotation (Num, optional): 高级colorbar旋转. Defaults to -90.
        manual_colorbar_pad (Num, optional): 高级colorbar标题间隔距离. Defaults to 20.
        manual_colorbar_draw_border (bool, optional): 高级colorbar轮廓. Defaults to True.
        manual_colorbar_tickline (bool, optional): 高级colorbar tick线. Defaults to False.
        manual_colorbar_nticks (bool, optional): 高级colorbar tick数量. Defaults to False.

    Returns:
        plt.Figure: _description_
    """
    # 设置默认值
    if vmax is None:
        vmax = np.max((np.max(connectome), -np.min(connectome)))
    if vmin is None:
        vmin = np.min((np.min(connectome), -np.max(connectome)))
    count = connectome.shape[0]
    count_half = int(count / 2)
    if labels is None:
        labels = [str(i) for i in range(count_half)]
    if node_colors is None:
        node_colors = ["#ff8f8f"] * count_half
    labels = labels + [i + " " for i in labels[::-1]]
    node_colors = node_colors + list(node_colors[::-1])
    node_angles = mne.viz.circular_layout(
        labels, labels, group_boundaries=[0, len(labels) / 2]
    )
    # 常规矩阵需要做对称转换
    data_upper_left = connectome[0:count_half, 0:count_half]
    data_down_right = connectome[count_half:count, count_half:count]
    data_down_left = connectome[count_half:count, 0:count_half]
    data_upper_right = connectome[0:count_half, count_half:count]
    data_down_right = data_down_right[::-1][:, ::-1]
    data_down_left = data_down_left[::-1]
    data_upper_right = data_upper_right[:, ::-1]
    connectome_upper = np.concatenate((data_upper_left, data_upper_right), axis=1)
    connectome_lower = np.concatenate((data_down_left, data_down_right), axis=1)
    connectome = np.concatenate((connectome_upper, connectome_lower), axis=0)
    # 画图
    fig, ax = plt.subplots(figsize=figsize, subplot_kw={"polar": True})
    fig.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.1)
    plot_connectivity_circle(
        connectome,
        labels,
        node_angles=node_angles,
        node_colors=node_colors,
        fontsize_names=labels_fontsize,
        facecolor=face_color,
        node_edgecolor=nodeedge_color,
        textcolor=text_color,
        colormap=cmap,
        vmin=vmin,
        vmax=vmax,
        linewidth=linewidth,
        title=title_name,
        fontsize_title=title_fontsize,
        colorbar=colorbar,
        colorbar_size=colorbar_size,
        colorbar_pos=colorbar_pos,
        fontsize_colorbar=colorbar_fontsize,
        fig=fig,
        ax=ax,
        interactive=False,
        show=False,
    )
    # 如有需要,禁用自动colorbar,手动生成colorbar
    if manual_colorbar:
        # 手动创建colorbar,拥有更多的设置
        cax = fig.add_axes(manual_colorbar_pos)
        norm = plt.Normalize(vmin=vmin, vmax=vmax)
        sm = plt.cm.ScalarMappable(cmap=manual_cmap, norm=norm)
        sm.set_array([])
        cbar = fig.colorbar(sm, cax=cax)
        cbar.outline.set_visible(manual_colorbar_draw_border)
        cbar.ax.set_ylabel(
            manual_colorbar_name,
            fontsize=manual_colorbar_label_fontsize,
            rotation=manual_colorbar_rotation,
            labelpad=manual_colorbar_pad,
        )
        if not manual_colorbar_tickline:
            cbar.ax.tick_params(length=0)  # 不显示竖线
        cbar.ax.yaxis.set_ticks_position("left")
        cbar.ax.tick_params(labelsize=manual_colorbar_fontsize)
        if manual_colorbar_nticks:
            ticks = np.linspace(vmin, vmax, manual_colorbar_nticks)
            cbar.set_ticks(ticks)
    return fig

plotfig.brain_surface

plot_brain_surface_figure

plot_brain_surface_figure(data, species='human', atlas='glasser', surf='veryinflated', ax=None, vmin=None, vmax=None, cmap='Reds', colorbar=True, colorbar_location='right', colorbar_label_name='', colorbar_label_rotation=0, colorbar_decimals=1, colorbar_fontsize=8, colorbar_nticks=2, colorbar_shrink=0.15, colorbar_aspect=8, colorbar_draw_border=False, title_name='', title_fontsize=12, as_outline=False)

在大脑皮层表面绘制数值数据的函数。

脑区图是一种用于在大脑皮层表面可视化数值数据的图表。它能够将不同脑区的数值映射到大脑皮层的相应区域, 并以颜色编码的方式展示这些数值的分布情况。这种图表常用于展示神经科学研究中的各种脑区指标, 如功能连接强度、激活程度或其他数值化的大脑特征。

本函数基于 surfplot 库开发,提供了一个统一且简化的接口来绘制人脑、猕猴脑和黑猩猩脑的表面图。 支持多种脑图谱,包括人脑的 Glasser 和 BNA 图谱、猕猴脑的 CHARM⅚、BNA 和 D99 图谱, 以及黑猩猩脑的 BNA 图谱。

Parameters:

Name Type Description Default
data dict[str, float]

包含脑区名称和对应数值的字典,键为脑区名称(如"lh_bankssts"),值为数值

required
species str

物种名称,支持"human"、"chimpanzee"、"macaque". Defaults to "human".

'human'
atlas str

脑图集名称,根据物种不同可选不同图集。人上包括"glasser"、"bna",黑猩猩上包括"bna",猕猴上包括"charm5"、"charm6"、"bna"以及"d99". Defaults to "glasser".

'glasser'
surf str

大脑皮层表面类型,如"inflated"、"veryinflated"、"midthickness"等. Defaults to "veryinflated".

'veryinflated'
ax Axes | None

matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.

None
vmin Num | None

颜色映射的最小值,None表示使用数据中的最小值. Defaults to None.

None
vmax Num | None

颜色映射的最大值,None表示使用数据中的最大值. Defaults to None.

None
cmap str

颜色映射方案,如"Reds"、"Blues"、"viridis"等. Defaults to "Reds".

'Reds'
colorbar bool

是否显示颜色条. Defaults to True.

True
colorbar_location str

颜色条位置,可选"left"、"right"、"top"、"bottom". Defaults to "right".

'right'
colorbar_label_name str

颜色条标签名称. Defaults to "".

''
colorbar_label_rotation int

颜色条标签旋转角度. Defaults to 0.

0
colorbar_decimals int

颜色条刻度标签的小数位数. Defaults to 1.

1
colorbar_fontsize int

颜色条字体大小. Defaults to 8.

8
colorbar_nticks int

颜色条刻度数量. Defaults to 2.

2
colorbar_shrink float

颜色条收缩比例. Defaults to 0.15.

0.15
colorbar_aspect int

颜色条宽高比. Defaults to 8.

8
colorbar_draw_border bool

是否绘制颜色条边框. Defaults to False.

False
title_name str

图形标题. Defaults to "".

''
title_fontsize int

标题字体大小. Defaults to 12.

12
as_outline bool

是否以轮廓线形式显示. Defaults to False.

False

Raises:

Type Description
ValueError

当指定的物种不支持时抛出

ValueError

当指定的图集不支持时抛出

ValueError

当数据为空时抛出

ValueError

当vmin大于vmax时抛出

Returns:

Name Type Description
Axes Axes

包含绘制图像的matplotlib坐标轴对象

Source code in src/plotfig/brain_surface.py
def plot_brain_surface_figure(
    data: dict[str, float],
    species: str = "human",
    atlas: str = "glasser",
    surf: str = "veryinflated",
    ax: Axes | None = None,
    vmin: Num | None = None,
    vmax: Num | None = None,
    cmap: str = "Reds",
    colorbar: bool = True,
    colorbar_location: str = "right",
    colorbar_label_name: str = "",
    colorbar_label_rotation: int = 0,
    colorbar_decimals: int = 1,
    colorbar_fontsize: int = 8,
    colorbar_nticks: int = 2,
    colorbar_shrink: float = 0.15,
    colorbar_aspect: int = 8,
    colorbar_draw_border: bool = False,
    title_name: str = "",
    title_fontsize: int = 12,
    as_outline: bool = False,
) -> Axes: 
    """在大脑皮层表面绘制数值数据的函数。

    脑区图是一种用于在大脑皮层表面可视化数值数据的图表。它能够将不同脑区的数值映射到大脑皮层的相应区域,
    并以颜色编码的方式展示这些数值的分布情况。这种图表常用于展示神经科学研究中的各种脑区指标,
    如功能连接强度、激活程度或其他数值化的大脑特征。

    本函数基于 surfplot 库开发,提供了一个统一且简化的接口来绘制人脑、猕猴脑和黑猩猩脑的表面图。
    支持多种脑图谱,包括人脑的 Glasser 和 BNA 图谱、猕猴脑的 CHARM5/6、BNA 和 D99 图谱,
    以及黑猩猩脑的 BNA 图谱。

    Args:
        data (dict[str, float]): 包含脑区名称和对应数值的字典,键为脑区名称(如"lh_bankssts"),值为数值
        species (str, optional): 物种名称,支持"human"、"chimpanzee"、"macaque". Defaults to "human".
        atlas (str, optional): 脑图集名称,根据物种不同可选不同图集。人上包括"glasser"、"bna",黑猩猩上包括"bna",猕猴上包括"charm5"、"charm6"、"bna"以及"d99". Defaults to "glasser".
        surf (str, optional): 大脑皮层表面类型,如"inflated"、"veryinflated"、"midthickness"等. Defaults to "veryinflated".
        ax (Axes | None, optional): matplotlib的坐标轴对象,如果为None则使用当前坐标轴. Defaults to None.
        vmin (Num | None, optional): 颜色映射的最小值,None表示使用数据中的最小值. Defaults to None.
        vmax (Num | None, optional): 颜色映射的最大值,None表示使用数据中的最大值. Defaults to None.
        cmap (str, optional): 颜色映射方案,如"Reds"、"Blues"、"viridis"等. Defaults to "Reds".
        colorbar (bool, optional): 是否显示颜色条. Defaults to True.
        colorbar_location (str, optional): 颜色条位置,可选"left"、"right"、"top"、"bottom". Defaults to "right".
        colorbar_label_name (str, optional): 颜色条标签名称. Defaults to "".
        colorbar_label_rotation (int, optional): 颜色条标签旋转角度. Defaults to 0.
        colorbar_decimals (int, optional): 颜色条刻度标签的小数位数. Defaults to 1.
        colorbar_fontsize (int, optional): 颜色条字体大小. Defaults to 8.
        colorbar_nticks (int, optional): 颜色条刻度数量. Defaults to 2.
        colorbar_shrink (float, optional): 颜色条收缩比例. Defaults to 0.15.
        colorbar_aspect (int, optional): 颜色条宽高比. Defaults to 8.
        colorbar_draw_border (bool, optional): 是否绘制颜色条边框. Defaults to False.
        title_name (str, optional): 图形标题. Defaults to "".
        title_fontsize (int, optional): 标题字体大小. Defaults to 12.
        as_outline (bool, optional): 是否以轮廓线形式显示. Defaults to False.

    Raises:
        ValueError: 当指定的物种不支持时抛出
        ValueError: 当指定的图集不支持时抛出
        ValueError: 当数据为空时抛出
        ValueError: 当vmin大于vmax时抛出

    Returns:
        Axes: 包含绘制图像的matplotlib坐标轴对象
    """
    # 获取或创建坐标轴对象
    ax = ax or plt.gca()

    # 提取所有数值用于确定vmin和vmax
    values = list(data.values())
    if not values:
        raise ValueError("data 不能为空")
    vmin = min(values) if vmin is None else vmin
    vmax = max(values) if vmax is None else vmax
    if vmin == vmax:
        vmin, vmax = min(0, vmin), max(0, vmax)
    if vmin > vmax:
        raise ValueError("vmin必须小于等于vmax")

    # 设置数据文件路径
    # 定义不同物种、表面类型和图集的文件路径信息
    atlas_info = {
        "human": {
            "surf": {
                "lh": f"surfaces/human_fsLR/tpl-fsLR_den-32k_hemi-L_{surf}.surf.gii",
                "rh": f"surfaces/human_fsLR/tpl-fsLR_den-32k_hemi-R_{surf}.surf.gii",
            },
            "atlas": {
                "glasser": {
                    "lh": "atlases/human_Glasser/fsaverage.L.Glasser.32k_fs_LR.label.gii",
                    "rh": "atlases/human_Glasser/fsaverage.R.Glasser.32k_fs_LR.label.gii",
                },
                "bna": {
                    "lh": "atlases/human_BNA/fsaverage.L.BNA.32k_fs_LR.label.gii",
                    "rh": "atlases/human_BNA/fsaverage.R.BNA.32k_fs_LR.label.gii",
                },
            },
        },
        "chimpanzee": {
            "surf": {
                "lh": f"surfaces/chimpanzee_BNA/ChimpYerkes29_v1.2.L.{surf}.32k_fs_LR.surf.gii",
                "rh": f"surfaces/chimpanzee_BNA/ChimpYerkes29_v1.2.R.{surf}.32k_fs_LR.surf.gii",
            },
            "atlas": {
                "bna": {
                    "lh": "atlases/chimpanzee_BNA/ChimpBNA.L.32k_fs_LR.label.gii",
                    "rh": "atlases/chimpanzee_BNA/ChimpBNA.R.32k_fs_LR.label.gii",
                },
            }
        },
        "macaque": {
            "surf": {
                "lh": f"surfaces/macaque_BNA/civm.L.{surf}.32k_fs_LR.surf.gii",
                "rh": f"surfaces/macaque_BNA/civm.R.{surf}.32k_fs_LR.surf.gii",
            },
            "atlas": {
                "charm5": {
                    "lh": "atlases/macaque_CHARM5/L.charm5.label.gii",
                    "rh": "atlases/macaque_CHARM5/R.charm5.label.gii",
                },
                "charm6": {
                    "lh": "atlases/macaque_CHARM6/L.charm6.label.gii",
                    "rh": "atlases/macaque_CHARM6/R.charm6.label.gii",
                },
                "bna": {
                    "lh": "atlases/macaque_BNA/MBNA_124_32k_L.label.gii",
                    "rh": "atlases/macaque_BNA/MBNA_124_32k_R.label.gii",
                },
                "d99": {
                    "lh": "atlases/macaque_D99/L.d99.label.gii",
                    "rh": "atlases/macaque_D99/R.d99.label.gii",
                },
            }
        }
    }

    # 检查物种是否支持
    if species not in atlas_info:
        raise ValueError(f"Unsupported species: {species}. Supported species are: {list(atlas_info.keys())}")
    else:
        # 检查指定物种的图集是否支持
        if atlas not in atlas_info[species]["atlas"]:
            raise ValueError(f"Unsupported {atlas} atlas for {species}")

    # 创建Plot对象,用于绘制大脑皮层
    p = Plot(
        NEURODATA / atlas_info[species]["surf"]["lh"],
        NEURODATA / atlas_info[species]["surf"]["rh"],
    )

    # 分离左半球和右半球的数据
    hemisphere_data = {}
    for hemi in ["lh", "rh"]:
        hemi_data = {k: v for k, v in data.items() if k.startswith(f"{hemi}_")}
        hemi_parc = _map_labels_to_values(
            hemi_data, NEURODATA / atlas_info[species]["atlas"][atlas][hemi]
        )
        hemisphere_data[hemi] = hemi_parc

    # 画图
    # colorbar参数设置(用列表统一管理,便于维护)
    colorbar_params = [
        ("location", colorbar_location),
        ("label_direction", colorbar_label_rotation),
        ("decimals", colorbar_decimals),
        ("fontsize", colorbar_fontsize),
        ("n_ticks", colorbar_nticks),
        ("shrink", colorbar_shrink),
        ("aspect", colorbar_aspect),
        ("draw_border", colorbar_draw_border),
    ]
    colorbar_kws = {k: v for k, v in colorbar_params}
    # 添加图层到绘图对象
    p.add_layer(
        {"left": hemisphere_data["lh"], "right": hemisphere_data["rh"]},
        cbar=colorbar,
        cmap=cmap,
        color_range=(vmin, vmax),
        cbar_label=colorbar_label_name,
        zero_transparent=False,
        as_outline=as_outline,
    )
    # 构建坐标轴并应用颜色条设置
    ax = p.build_axis(ax=ax, cbar_kws=colorbar_kws)
    # 设置图形标题
    ax.set_title(title_name, fontsize=title_fontsize)

    return ax

plotfig.brain_surface_deprecated

plot_human_brain_figure

plot_human_brain_figure(data, surf='veryinflated', atlas='glasser', vmin=None, vmax=None, plot=True, cmap='Reds', as_outline=False, colorbar=True, colorbar_location='right', colorbar_label_name='', colorbar_label_rotation=0, colorbar_decimals=1, colorbar_fontsize=8, colorbar_nticks=2, colorbar_shrink=0.15, colorbar_aspect=8, colorbar_draw_border=False, title_name='', title_fontsize=15, title_y=0.9, rjx_colorbar=False, rjx_colorbar_direction='vertical', horizontal_center=True, rjx_colorbar_outline=False, rjx_colorbar_label_name='', rjx_colorbar_tick_fontsize=10, rjx_colorbar_label_fontsize=10, rjx_colorbar_tick_rotation=0, rjx_colorbar_tick_length=0, rjx_colorbar_nticks=2)

绘制人类大脑表面图,支持 Glasser 和 BNA 图谱。

Parameters:

Name Type Description Default
data dict[str, float]

包含 ROI 名称及其对应值的字典。

required
surf str

大脑表面类型(如 "veryinflated", "inflated")。默认为 "veryinflated"。

'veryinflated'
atlas str

使用的图谱名称,支持 "glasser" 或 "bna"。默认为 "glasser"。

'glasser'
vmin Num

颜色映射的最小值。可以是整数或浮点数。默认为 None。

None
vmax Num

颜色映射的最大值。可以是整数或浮点数。默认为 None。

None
plot bool

是否直接绘制图形。默认为 True。

True
cmap str

颜色映射方案。默认为 "Reds"。

'Reds'
as_outline bool

是否以轮廓形式显示颜色层。默认为 False。

False
colorbar bool

是否显示颜色条。默认为 True。

True
colorbar_location str

颜色条的位置。默认为 "right"。

'right'
colorbar_label_name str

颜色条的标签名称。默认为空字符串。

''
colorbar_label_rotation int

颜色条标签的旋转角度。默认为 0。

0
colorbar_decimals int

颜色条刻度的小数位数。默认为 1。

1
colorbar_fontsize int

颜色条标签的字体大小。默认为 8。

8
colorbar_nticks int

颜色条上的刻度数量。默认为 2。

2
colorbar_shrink float

颜色条的缩放比例。默认为 0.15。

0.15
colorbar_aspect int

颜色条的宽高比。默认为 8。

8
colorbar_draw_border bool

是否绘制颜色条边框。默认为 False。

False
title_name str

图形标题。默认为空字符串。

''
title_fontsize int

标题字体大小。默认为 15。

15
title_y float

标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。

0.9
rjx_colorbar bool

是否使用自定义颜色条。默认为 False。

False
rjx_colorbar_direction str

自定义颜色条方向,支持 "vertical" 或 "horizontal"。默认为 "vertical"。

'vertical'
horizontal_center bool

水平颜色条是否居中。默认为 True。

True
rjx_colorbar_outline bool

自定义颜色条是否显示边框。默认为 False。

False
rjx_colorbar_label_name str

自定义颜色条标签名称。默认为空字符串。

''
rjx_colorbar_tick_fontsize int

自定义颜色条刻度字体大小。默认为 10。

10
rjx_colorbar_label_fontsize int

自定义颜色条标签字体大小。默认为 10。

10
rjx_colorbar_tick_rotation int

自定义颜色条刻度标签旋转角度。默认为 0。

0
rjx_colorbar_tick_length int

自定义颜色条刻度长度。默认为 0。

0
rjx_colorbar_nticks int

自定义颜色条上的刻度数量。默认为 2。

2

Returns:

Type Description
Figure | tuple[ndarray, ndarray]

Union[plt.Figure, tuple[np.ndarray, np.ndarray]]: 如果 plot=True,返回 matplotlib 的 Figure 对象;

Figure | tuple[ndarray, ndarray]

否则返回左右脑数据数组的元组 (lh_parc, rh_parc)

Source code in src/plotfig/brain_surface_deprecated.py
def plot_human_brain_figure(
    data: dict[str, float],
    surf: str = "veryinflated",
    atlas: str = "glasser",
    vmin: Num | None = None,
    vmax: Num | None = None,
    plot: bool = True,
    cmap: str = "Reds",
    as_outline: bool = False,
    colorbar: bool = True,
    colorbar_location: str = "right",
    colorbar_label_name: str = "",
    colorbar_label_rotation: int = 0,
    colorbar_decimals: int = 1,
    colorbar_fontsize: int = 8,
    colorbar_nticks: int = 2,
    colorbar_shrink: float = 0.15,
    colorbar_aspect: int = 8,
    colorbar_draw_border: bool = False,
    title_name: str = "",
    title_fontsize: int = 15,
    title_y: float = 0.9,
    rjx_colorbar: bool = False,
    rjx_colorbar_direction: str = "vertical",
    horizontal_center: bool = True,
    rjx_colorbar_outline: bool = False,
    rjx_colorbar_label_name: str = "",
    rjx_colorbar_tick_fontsize: int = 10,
    rjx_colorbar_label_fontsize: int = 10,
    rjx_colorbar_tick_rotation: int = 0,
    rjx_colorbar_tick_length: int = 0,
    rjx_colorbar_nticks: int = 2,
) -> plt.Figure | tuple[np.ndarray, np.ndarray]:
    """
    绘制人类大脑表面图,支持 Glasser 和 BNA 图谱。

    Args:
        data (dict[str, float]): 包含 ROI 名称及其对应值的字典。
        surf (str, optional): 大脑表面类型(如 "veryinflated", "inflated")。默认为 "veryinflated"。
        atlas (str, optional): 使用的图谱名称,支持 "glasser" 或 "bna"。默认为 "glasser"。
        vmin (Num, optional): 颜色映射的最小值。可以是整数或浮点数。默认为 None。
        vmax (Num, optional): 颜色映射的最大值。可以是整数或浮点数。默认为 None。
        plot (bool, optional): 是否直接绘制图形。默认为 True。
        cmap (str, optional): 颜色映射方案。默认为 "Reds"。
        as_outline (bool, optional): 是否以轮廓形式显示颜色层。默认为 False。
        colorbar (bool, optional): 是否显示颜色条。默认为 True。
        colorbar_location (str, optional): 颜色条的位置。默认为 "right"。
        colorbar_label_name (str, optional): 颜色条的标签名称。默认为空字符串。
        colorbar_label_rotation (int, optional): 颜色条标签的旋转角度。默认为 0。
        colorbar_decimals (int, optional): 颜色条刻度的小数位数。默认为 1。
        colorbar_fontsize (int, optional): 颜色条标签的字体大小。默认为 8。
        colorbar_nticks (int, optional): 颜色条上的刻度数量。默认为 2。
        colorbar_shrink (float, optional): 颜色条的缩放比例。默认为 0.15。
        colorbar_aspect (int, optional): 颜色条的宽高比。默认为 8。
        colorbar_draw_border (bool, optional): 是否绘制颜色条边框。默认为 False。
        title_name (str, optional): 图形标题。默认为空字符串。
        title_fontsize (int, optional): 标题字体大小。默认为 15。
        title_y (float, optional): 标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。
        rjx_colorbar (bool, optional): 是否使用自定义颜色条。默认为 False。
        rjx_colorbar_direction (str, optional): 自定义颜色条方向,支持 "vertical" 或 "horizontal"。默认为 "vertical"。
        horizontal_center (bool, optional): 水平颜色条是否居中。默认为 True。
        rjx_colorbar_outline (bool, optional): 自定义颜色条是否显示边框。默认为 False。
        rjx_colorbar_label_name (str, optional): 自定义颜色条标签名称。默认为空字符串。
        rjx_colorbar_tick_fontsize (int, optional): 自定义颜色条刻度字体大小。默认为 10。
        rjx_colorbar_label_fontsize (int, optional): 自定义颜色条标签字体大小。默认为 10。
        rjx_colorbar_tick_rotation (int, optional): 自定义颜色条刻度标签旋转角度。默认为 0。
        rjx_colorbar_tick_length (int, optional): 自定义颜色条刻度长度。默认为 0。
        rjx_colorbar_nticks (int, optional): 自定义颜色条上的刻度数量。默认为 2。

    Returns:
        Union[plt.Figure, tuple[np.ndarray, np.ndarray]]: 如果 `plot=True`,返回 matplotlib 的 Figure 对象;
        否则返回左右脑数据数组的元组 `(lh_parc, rh_parc)`。
    """
    # 发出弃用警告
    warnings.warn(
        "plot_human_brain_figure 即将弃用,请使用 plot_brain_surface_figure 替代。未来版本将移除本函数。",
        DeprecationWarning,
        stacklevel=2
    )

    # 设置必要文件路径
    current_dir = op.dirname(__file__)
    neuromaps_data_dir = op.join(current_dir, "data/neurodata")
    if atlas == "glasser":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_Glasser/fsaverage.L.Glasser.32k_fs_LR.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_Glasser/fsaverage.R.Glasser.32k_fs_LR.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables/human_glasser.csv"))
    elif atlas == "bna":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_BNA/fsaverage.L.BNA.32k_fs_LR.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_BNA/fsaverage.R.BNA.32k_fs_LR.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables", "human_bna.csv"))
    # 获取文件Underlay
    lh = op.join(
        neuromaps_data_dir,
        f"surfaces/human_fsLR/tpl-fsLR_den-32k_hemi-L_{surf}.surf.gii",
    )
    rh = op.join(
        neuromaps_data_dir,
        f"surfaces/human_fsLR/tpl-fsLR_den-32k_hemi-R_{surf}.surf.gii",
    )
    p = Plot(lh, rh)
    # 将原始数据拆分成左右脑数据
    lh_data, rh_data = {}, {}
    for roi in data:
        if "lh_" in roi:
            lh_data[roi] = data[roi]
        elif "rh_" in roi:
            rh_data[roi] = data[roi]
    # 加载图集分区数据
    lh_roi_list, rh_roi_list = (
        list(df["ROIs_name"])[0 : int(len(df["ROIs_name"]) / 2)],
        list(df["ROIs_name"])[int(len(df["ROIs_name"]) / 2) : len(df["ROIs_name"])],
    )
    # 处理左脑数据
    lh_parc = nib.load(lh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in lh_roi_list}
    for vertex_index, label in enumerate(lh_parc):
        if label - 1 >= 0:
            roi_vertics[lh_roi_list[label - 1]].append(vertex_index)
    lh_parc = np.full(lh_parc.shape, np.nan)
    for roi in lh_data:
        lh_parc[roi_vertics[roi]] = lh_data[roi]
    # 处理右脑数据
    rh_parc = nib.load(rh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in rh_roi_list}
    for vertex_index, label in enumerate(rh_parc):
        if label - 1 - len(lh_roi_list) >= 0:
            roi_vertics[rh_roi_list[label - 1 - len(lh_roi_list)]].append(vertex_index)
    rh_parc = np.full(rh_parc.shape, np.nan)
    for roi in rh_data:
        rh_parc[roi_vertics[roi]] = rh_data[roi]
    # 画图
    if plot:
        # 画图元素参数设置
        if vmin is None:
            vmin = min(data.values())
        if vmax is None:
            vmax = max(data.values())
        if vmin > vmax:
            print("vmin必须小于等于vmax")
            return
        if vmin == vmax:
            vmin = min(0, vmin)
            vmax = max(0, vmax)
        # colorbar参数设置
        colorbar_kws = {
            "location": colorbar_location,
            "label_direction": colorbar_label_rotation,
            "decimals": colorbar_decimals,
            "fontsize": colorbar_fontsize,
            "n_ticks": colorbar_nticks,
            "shrink": colorbar_shrink,
            "aspect": colorbar_aspect,
            "draw_border": colorbar_draw_border,
        }
        p.add_layer(
            {"left": lh_parc, "right": rh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
            as_outline=as_outline,
        )
        fig = p.build(cbar_kws=colorbar_kws)
        fig.suptitle(title_name, fontsize=title_fontsize, y=title_y)
        ############################################### rjx_colorbar ###############################################
        sm = ScalarMappable(cmap=cmap)
        sm.set_array((vmin, vmax))  # 设置值范围
        if rjx_colorbar:
            if rjx_colorbar_direction == "vertical":
                formatter = ScalarFormatter(useMathText=True)  # 科学计数法相关
                formatter.set_powerlimits(
                    (-3, 3)
                )  # <=-1也就是小于等于0.1,>=2,也就是大于等于100,会写成科学计数法
                cax = fig.add_axes(
                    [1, 0.425, 0.01, 0.15]
                )  # [left, bottom, width, height]
                cbar = fig.colorbar(
                    sm, cax=cax, orientation="vertical", cmap=cmap
                )  # "vertical", "horizontal"
                cbar.outline.set_visible(rjx_colorbar_outline)
                cbar.ax.set_ylabel(
                    rjx_colorbar_label_name, fontsize=rjx_colorbar_label_fontsize
                )
                cbar.ax.yaxis.set_label_position(
                    "left"
                )  # 原本设置y轴label默认在右边,现在换到左边
                cbar.ax.tick_params(
                    axis="y",
                    which="major",
                    labelsize=rjx_colorbar_tick_fontsize,
                    rotation=rjx_colorbar_tick_rotation,
                    length=rjx_colorbar_tick_length,
                )
                cbar.set_ticks(np.linspace(vmin, vmax, rjx_colorbar_nticks))
                if vmax < 0.001 or vmax > 1000:  # y轴设置科学计数法
                    cbar.ax.yaxis.set_major_formatter(formatter)
                    cbar.ax.yaxis.get_offset_text().set_visible(
                        False
                    )  # 隐藏默认的偏移文本
                    exponent = math.floor(math.log10(vmax))
                    # 手动添加文本
                    cbar.ax.text(
                        1.05,
                        1.15,
                        rf"$\times 10^{{{exponent}}}$",
                        transform=cbar.ax.transAxes,
                        fontsize=rjx_colorbar_tick_fontsize,
                        verticalalignment="bottom",
                        horizontalalignment="left",
                    )
            elif rjx_colorbar_direction == "horizontal":
                if horizontal_center:
                    cax = fig.add_axes([0.44, 0.5, 0.15, 0.01])
                else:
                    cax = fig.add_axes([0.44, 0.05, 0.15, 0.01])
                cbar = fig.colorbar(sm, cax=cax, orientation="horizontal", cmap=cmap)
                cbar.outline.set_visible(rjx_colorbar_outline)
                cbar.ax.set_title(
                    rjx_colorbar_label_name, fontsize=rjx_colorbar_label_fontsize
                )
                cbar.ax.tick_params(
                    axis="x",
                    which="major",
                    labelsize=rjx_colorbar_tick_fontsize,
                    rotation=rjx_colorbar_tick_rotation,
                    length=rjx_colorbar_tick_length,
                )
                if vmax < 0.001 or vmax > 1000:  # y轴设置科学计数法
                    cbar.ax.xaxis.set_major_formatter(formatter)
                cbar.set_ticks(np.linspace(vmin, vmax, rjx_colorbar_nticks))
            ########################################### rjx_colorbar ###############################################
        return fig
    return lh_parc, rh_parc

plot_human_hemi_brain_figure

plot_human_hemi_brain_figure(data, hemi='lh', surf='veryinflated', atlas='glasser', vmin=None, vmax=None, cmap='Reds', colorbar=True, colorbar_location='right', colorbar_label_name='', colorbar_label_rotation=0, colorbar_decimals=1, colorbar_fontsize=8, colorbar_nticks=2, colorbar_shrink=0.15, colorbar_aspect=8, colorbar_draw_border=False, title_name='', title_fontsize=15, title_y=0.9)
Source code in src/plotfig/brain_surface_deprecated.py
def plot_human_hemi_brain_figure(
    data: dict[str, float],
    hemi: str = "lh",
    surf: str = "veryinflated",
    atlas: str = "glasser",
    vmin: Num | None = None,
    vmax: Num | None = None,
    cmap: str = "Reds",
    colorbar: bool = True,
    colorbar_location: str = "right",
    colorbar_label_name: str = "",
    colorbar_label_rotation: int = 0,
    colorbar_decimals: int = 1,
    colorbar_fontsize: int = 8,
    colorbar_nticks: int = 2,
    colorbar_shrink: float = 0.15,
    colorbar_aspect: int = 8,
    colorbar_draw_border: bool = False,
    title_name: str = "",
    title_fontsize: int = 15,
    title_y: float = 0.9,
) -> plt.Figure | None:
    warnings.warn(
        "plot_human_hemi_brain_figure 即将弃用,请使用 plot_brain_surface_figure 替代。未来版本将移除本函数。",
        DeprecationWarning,
        stacklevel=2
    )
    """
    绘制人类大脑单侧(左脑或右脑)表面图,支持 Glasser 和 BNA 图谱。

    Args:
        data (dict[str, float]): 包含 ROI 名称及其对应值的字典。
        hemi (str, optional): 脑半球选择,支持 "lh"(左脑)或 "rh"(右脑)。默认为 "lh"。
        surf (str, optional): 大脑表面类型(如 "veryinflated", "inflated")。默认为 "veryinflated"。
        atlas (str, optional): 使用的图谱名称,支持 "glasser" 或 "bna"。默认为 "glasser"。
        vmin (Num, optional): 颜色映射的最小值。可以是整数或浮点数。默认为 None。
        vmax (Num, optional): 颜色映射的最大值。可以是整数或浮点数。默认为 None。
        cmap (str, optional): 颜色映射方案。默认为 "Reds"。
        colorbar (bool, optional): 是否显示颜色条。默认为 True。
        colorbar_location (str, optional): 颜色条的位置。默认为 "right"。
        colorbar_label_name (str, optional): 颜色条的标签名称。默认为空字符串。
        colorbar_label_rotation (int, optional): 颜色条标签的旋转角度。默认为 0。
        colorbar_decimals (int, optional): 颜色条刻度的小数位数。默认为 1。
        colorbar_fontsize (int, optional): 颜色条标签的字体大小。默认为 8。
        colorbar_nticks (int, optional): 颜色条上的刻度数量。默认为 2。
        colorbar_shrink (float, optional): 颜色条的缩放比例。默认为 0.15。
        colorbar_aspect (int, optional): 颜色条的宽高比。默认为 8。
        colorbar_draw_border (bool, optional): 是否绘制颜色条边框。默认为 False。
        title_name (str, optional): 图形标题。默认为空字符串。
        title_fontsize (int, optional): 标题字体大小。默认为 15。
        title_y (float, optional): 标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。

    Returns:
        plt.Figure: 返回一个 matplotlib 的 Figure 对象,表示生成的大脑表面图。
    """

    # 设置必要文件路径
    current_dir = op.dirname(__file__)
    neuromaps_data_dir = op.join(current_dir, "data/neurodata")
    if atlas == "glasser":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_Glasser/fsaverage.L.Glasser.32k_fs_LR.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_Glasser/fsaverage.R.Glasser.32k_fs_LR.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables", "human_glasser.csv"))
    elif atlas == "bna":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_BNA/fsaverage.L.BNA.32k_fs_LR.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/human_BNA/fsaverage.R.BNA.32k_fs_LR.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables", "human_bna.csv"))
    # 获取文件Underlay

    lh = op.join(
        neuromaps_data_dir,
        f"surfaces/human_fsLR/tpl-fsLR_den-32k_hemi-L_{surf}.surf.gii",
    )
    rh = op.join(
        neuromaps_data_dir,
        f"surfaces/human_fsLR/tpl-fsLR_den-32k_hemi-R_{surf}.surf.gii",
    )
    if hemi == "lh":
        p = Plot(lh, size=(800, 400), zoom=1.2)
    elif hemi == "rh":
        p = Plot(rh, size=(800, 400), zoom=1.2)
    # 将原始数据拆分成左右脑数据
    lh_data, rh_data = {}, {}
    for roi in data:
        if "lh_" in roi:
            lh_data[roi] = data[roi]
        elif "rh_" in roi:
            rh_data[roi] = data[roi]
    # 加载图集分区数据
    lh_roi_list, rh_roi_list = (
        list(df["ROIs_name"])[0 : int(len(df["ROIs_name"]) / 2)],
        list(df["ROIs_name"])[int(len(df["ROIs_name"]) / 2) : len(df["ROIs_name"])],
    )
    # 处理左脑数据
    lh_parc = nib.load(lh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in lh_roi_list}
    for vertex_index, label in enumerate(lh_parc):
        if label - 1 >= 0:
            roi_vertics[lh_roi_list[label - 1]].append(vertex_index)
    lh_parc = np.full(lh_parc.shape, np.nan)
    for roi in lh_data:
        lh_parc[roi_vertics[roi]] = lh_data[roi]
    # 处理右脑数据
    rh_parc = nib.load(rh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in rh_roi_list}
    for vertex_index, label in enumerate(rh_parc):
        if label - 1 - len(lh_roi_list) >= 0:
            roi_vertics[rh_roi_list[label - 1 - len(lh_roi_list)]].append(vertex_index)
    rh_parc = np.full(rh_parc.shape, np.nan)
    for roi in rh_data:
        rh_parc[roi_vertics[roi]] = rh_data[roi]
    # 画图元素参数设置
    if vmin is None:
        vmin = min(data.values())
    if vmax is None:
        vmax = max(data.values())
    if vmin > vmax:
        print("vmin必须小于等于vmax")
        return
    if vmin == vmax:
        vmin = min(0, vmin)
        vmax = max(0, vmax)
    # colorbar参数设置
    colorbar_kws = {
        "location": colorbar_location,
        "label_direction": colorbar_label_rotation,
        "decimals": colorbar_decimals,
        "fontsize": colorbar_fontsize,
        "n_ticks": colorbar_nticks,
        "shrink": colorbar_shrink,
        "aspect": colorbar_aspect,
        "draw_border": colorbar_draw_border,
    }
    if hemi == "lh":
        p.add_layer(
            {"left": lh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )
    elif hemi == "rh":
        p.add_layer(
            {"left": rh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )  # 很怪,但是这里就是写“{'left': rh_parc}”
    fig = p.build(cbar_kws=colorbar_kws)
    fig.suptitle(title_name, fontsize=title_fontsize, y=title_y)
    return fig

plot_chimpanzee_brain_figure

plot_chimpanzee_brain_figure(data, surf='veryinflated', atlas='bna', vmin=None, vmax=None, plot=True, cmap='Reds', colorbar=True, colorbar_location='right', colorbar_label_name='', colorbar_label_rotation=0, colorbar_decimals=1, colorbar_fontsize=8, colorbar_nticks=2, colorbar_shrink=0.15, colorbar_aspect=8, colorbar_draw_border=False, title_name='', title_fontsize=15, title_y=0.9, rjx_colorbar=False, rjx_colorbar_direction='vertical', horizontal_center=True, rjx_colorbar_outline=False, rjx_colorbar_label_name='', rjx_colorbar_tick_fontsize=10, rjx_colorbar_label_fontsize=10, rjx_colorbar_tick_rotation=0, rjx_colorbar_tick_length=0, rjx_colorbar_nticks=2)
Source code in src/plotfig/brain_surface_deprecated.py
def plot_chimpanzee_brain_figure(
    data: dict[str, float],
    surf: str = "veryinflated",
    atlas: str = "bna",
    vmin: Num | None = None,
    vmax: Num | None = None,
    plot: bool = True,
    cmap: str = "Reds",
    colorbar: bool = True,
    colorbar_location: str = "right",
    colorbar_label_name: str = "",
    colorbar_label_rotation: int = 0,
    colorbar_decimals: int = 1,
    colorbar_fontsize: int = 8,
    colorbar_nticks: int = 2,
    colorbar_shrink: float = 0.15,
    colorbar_aspect: int = 8,
    colorbar_draw_border: bool = False,
    title_name: str = "",
    title_fontsize: int = 15,
    title_y: float = 0.9,
    rjx_colorbar: bool = False,
    rjx_colorbar_direction: str = "vertical",
    horizontal_center: bool = True,
    rjx_colorbar_outline: bool = False,
    rjx_colorbar_label_name: str = "",
    rjx_colorbar_tick_fontsize: int = 10,
    rjx_colorbar_label_fontsize: int = 10,
    rjx_colorbar_tick_rotation: int = 0,
    rjx_colorbar_tick_length: int = 0,
    rjx_colorbar_nticks: int = 2,
) -> plt.Figure | tuple[np.ndarray, np.ndarray]:
    warnings.warn(
        "plot_chimpanzee_brain_figure 即将弃用,请使用 plot_brain_surface_figure 替代。未来版本将移除本函数。",
        DeprecationWarning,
        stacklevel=2
    )
    """
    绘制黑猩猩大脑表面图,支持 BNA 图谱。

    Args:
        data (dict[str, float]): 包含 ROI 名称及其对应值的字典。
        surf (str, optional): 大脑表面类型(如 "veryinflated", "midthickness")。默认为 "veryinflated"。
        atlas (str, optional): 使用的图谱名称,目前仅支持 "bna"。默认为 "bna"。
        vmin (Num, optional): 颜色映射的最小值。可以是整数或浮点数。默认为 None。
        vmax (Num, optional): 颜色映射的最大值。可以是整数或浮点数。默认为 None。
        plot (bool, optional): 是否直接绘制图形。默认为 True。
        cmap (str, optional): 颜色映射方案。默认为 "Reds"。
        colorbar (bool, optional): 是否显示颜色条。默认为 True。
        colorbar_location (str, optional): 颜色条的位置。默认为 "right"。
        colorbar_label_name (str, optional): 颜色条的标签名称。默认为空字符串。
        colorbar_label_rotation (int, optional): 颜色条标签的旋转角度。默认为 0。
        colorbar_decimals (int, optional): 颜色条刻度的小数位数。默认为 1。
        colorbar_fontsize (int, optional): 颜色条标签的字体大小。默认为 8。
        colorbar_nticks (int, optional): 颜色条上的刻度数量。默认为 2。
        colorbar_shrink (float, optional): 颜色条的缩放比例。默认为 0.15。
        colorbar_aspect (int, optional): 颜色条的宽高比。默认为 8。
        colorbar_draw_border (bool, optional): 是否绘制颜色条边框。默认为 False。
        title_name (str, optional): 图形标题。默认为空字符串。
        title_fontsize (int, optional): 标题字体大小。默认为 15。
        title_y (float, optional): 标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。
        rjx_colorbar (bool, optional): 是否使用自定义颜色条。默认为 False。
        rjx_colorbar_direction (str, optional): 自定义颜色条方向,支持 "vertical" 或 "horizontal"。默认为 "vertical"。
        horizontal_center (bool, optional): 水平颜色条是否居中。默认为 True。
        rjx_colorbar_outline (bool, optional): 自定义颜色条是否显示边框。默认为 False。
        rjx_colorbar_label_name (str, optional): 自定义颜色条标签名称。默认为空字符串。
        rjx_colorbar_tick_fontsize (int, optional): 自定义颜色条刻度字体大小。默认为 10。
        rjx_colorbar_label_fontsize (int, optional): 自定义颜色条标签字体大小。默认为 10。
        rjx_colorbar_tick_rotation (int, optional): 自定义颜色条刻度标签旋转角度。默认为 0。
        rjx_colorbar_tick_length (int, optional): 自定义颜色条刻度长度。默认为 0。
        rjx_colorbar_nticks (int, optional): 自定义颜色条上的刻度数量。默认为 2。

    Returns:
        Union[plt.Figure, tuple[np.ndarray, np.ndarray]]: 如果 `plot=True`,返回 matplotlib 的 Figure 对象;
        否则返回左右脑数据数组的元组 `(lh_parc, rh_parc)`。
    """

    # 设置必要文件路径
    current_dir = op.dirname(__file__)
    neuromaps_data_dir = op.join(current_dir, "data/neurodata")
    if atlas == "bna":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/chimpanzee_BNA/ChimpBNA.L.32k_fs_LR.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/chimpanzee_BNA/ChimpBNA.R.32k_fs_LR.label.gii",
        )
        df = pd.read_csv(
            op.join(current_dir, "data/atlas_tables", "chimpanzee_bna.csv")
        )
    # 获取文件Underlay
    lh = op.join(
        neuromaps_data_dir,
        f"surfaces/chimpanzee_BNA/ChimpYerkes29_v1.2.L.{surf}.32k_fs_LR.surf.gii",
    )
    rh = op.join(
        neuromaps_data_dir,
        f"surfaces/chimpanzee_BNA/ChimpYerkes29_v1.2.R.{surf}.32k_fs_LR.surf.gii",
    )
    p = Plot(lh, rh)
    # 将原始数据拆分成左右脑数据
    lh_data, rh_data = {}, {}
    for roi in data:
        if "lh_" in roi:
            lh_data[roi] = data[roi]
        elif "rh_" in roi:
            rh_data[roi] = data[roi]
    # 加载图集分区数据
    lh_roi_list, rh_roi_list = (
        list(df["ROIs_name"])[0 : int(len(df["ROIs_name"]) / 2)],
        list(df["ROIs_name"])[int(len(df["ROIs_name"]) / 2) : len(df["ROIs_name"])],
    )
    # 处理左脑数据
    lh_parc = nib.load(lh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in lh_roi_list}
    for vertex_index, label in enumerate(lh_parc):
        if label - 1 >= 0:
            roi_vertics[lh_roi_list[label - 1]].append(vertex_index)
    lh_parc = np.full(lh_parc.shape, np.nan)
    for roi in lh_data:
        lh_parc[roi_vertics[roi]] = lh_data[roi]
    # 处理右脑数据
    rh_parc = nib.load(rh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in rh_roi_list}
    for vertex_index, label in enumerate(rh_parc):
        if label - 1 - len(lh_roi_list) >= 0:
            roi_vertics[rh_roi_list[label - 1 - len(lh_roi_list)]].append(vertex_index)
    rh_parc = np.full(rh_parc.shape, np.nan)
    for roi in rh_data:
        rh_parc[roi_vertics[roi]] = rh_data[roi]
    # 画图
    if plot:
        # 画图元素参数设置
        if vmin is None:
            vmin = min(data.values())
        if vmax is None:
            vmax = max(data.values())
        if vmin > vmax:
            print("vmin必须小于等于vmax")
            return
        if vmin == vmax:
            vmin = min(0, vmin)
            vmax = max(0, vmax)
        # colorbar参数设置
        colorbar_kws = {
            "location": colorbar_location,
            "label_direction": colorbar_label_rotation,
            "decimals": colorbar_decimals,
            "fontsize": colorbar_fontsize,
            "n_ticks": colorbar_nticks,
            "shrink": colorbar_shrink,
            "aspect": colorbar_aspect,
            "draw_border": colorbar_draw_border,
        }
        p.add_layer(
            {"left": lh_parc, "right": rh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )
        fig = p.build(cbar_kws=colorbar_kws)
        fig.suptitle(title_name, fontsize=title_fontsize, y=title_y)
        ############################################### rjx_colorbar ###############################################
        sm = ScalarMappable(cmap=cmap)
        sm.set_array((vmin, vmax))  # 设置值范围
        if rjx_colorbar:
            formatter = ScalarFormatter(useMathText=True)  # 科学计数法相关
            formatter.set_powerlimits(
                (-3, 3)
            )  # <=-1也就是小于等于0.1,>=2,也就是大于等于100,会写成科学计数法
            if rjx_colorbar_direction == "vertical":
                cax = fig.add_axes(
                    [1, 0.425, 0.01, 0.15]
                )  # [left, bottom, width, height]
                cbar = fig.colorbar(
                    sm, cax=cax, orientation="vertical", cmap=cmap
                )  # "vertical", "horizontal"
                cbar.outline.set_visible(rjx_colorbar_outline)
                cbar.ax.set_ylabel(
                    rjx_colorbar_label_name, fontsize=rjx_colorbar_label_fontsize
                )
                cbar.ax.yaxis.set_label_position(
                    "left"
                )  # 原本设置y轴label默认在右边,现在换到左边
                cbar.ax.tick_params(
                    axis="y",
                    which="major",
                    labelsize=rjx_colorbar_tick_fontsize,
                    rotation=rjx_colorbar_tick_rotation,
                    length=rjx_colorbar_tick_length,
                )
                cbar.set_ticks(np.linspace(vmin, vmax, rjx_colorbar_nticks))
                if vmax < 0.001 or vmax > 1000:  # y轴设置科学计数法
                    cbar.ax.yaxis.set_major_formatter(formatter)
                    cbar.ax.yaxis.get_offset_text().set_visible(
                        False
                    )  # 隐藏默认的偏移文本
                    exponent = math.floor(math.log10(vmax))
                    # 手动添加文本
                    cbar.ax.text(
                        1.05,
                        1.15,
                        rf"$\times 10^{{{exponent}}}$",
                        transform=cbar.ax.transAxes,
                        fontsize=rjx_colorbar_tick_fontsize,
                        verticalalignment="bottom",
                        horizontalalignment="left",
                    )
            elif rjx_colorbar_direction == "horizontal":
                if horizontal_center:
                    cax = fig.add_axes([0.44, 0.5, 0.15, 0.01])
                else:
                    cax = fig.add_axes([0.44, 0.05, 0.15, 0.01])
                cbar = fig.colorbar(sm, cax=cax, orientation="horizontal", cmap=cmap)
                cbar.outline.set_visible(rjx_colorbar_outline)
                cbar.ax.set_title(
                    rjx_colorbar_label_name, fontsize=rjx_colorbar_label_fontsize
                )
                cbar.ax.tick_params(
                    axis="x",
                    which="major",
                    labelsize=rjx_colorbar_tick_fontsize,
                    rotation=rjx_colorbar_tick_rotation,
                    length=rjx_colorbar_tick_length,
                )
                if vmax < 0.001 or vmax > 1000:  # y轴设置科学计数法
                    cbar.ax.xaxis.set_major_formatter(formatter)
            cbar.set_ticks([vmin, vmax])
            ########################################### rjx_colorbar ###############################################
        return fig
    return lh_parc, rh_parc

plot_chimpanzee_hemi_brain_figure

plot_chimpanzee_hemi_brain_figure(data, hemi='lh', surf='veryinflated', atlas='bna', vmin=None, vmax=None, cmap='Reds', colorbar=True, colorbar_location='right', colorbar_label_name='', colorbar_label_rotation=0, colorbar_decimals=1, colorbar_fontsize=8, colorbar_nticks=2, colorbar_shrink=0.15, colorbar_aspect=8, colorbar_draw_border=False, title_name='', title_fontsize=15, title_y=0.9)
Source code in src/plotfig/brain_surface_deprecated.py
def plot_chimpanzee_hemi_brain_figure(
    data: dict[str, float],
    hemi: str = "lh",
    surf: str = "veryinflated",
    atlas: str = "bna",
    vmin: Num | None = None,
    vmax: Num | None = None,
    cmap: str = "Reds",
    colorbar: bool = True,
    colorbar_location: str = "right",
    colorbar_label_name: str = "",
    colorbar_label_rotation: int = 0,
    colorbar_decimals: int = 1,
    colorbar_fontsize: int = 8,
    colorbar_nticks: int = 2,
    colorbar_shrink: float = 0.15,
    colorbar_aspect: int = 8,
    colorbar_draw_border: bool = False,
    title_name: str = "",
    title_fontsize: int = 15,
    title_y: float = 0.9,
) -> plt.Figure:
    warnings.warn(
        "plot_chimpanzee_hemi_brain_figure 即将弃用,请使用 plot_brain_surface_figure 替代。未来版本将移除本函数。",
        DeprecationWarning,
        stacklevel=2
    )
    """
    绘制黑猩猩大脑单侧(左脑或右脑)表面图,支持 BNA 图谱。

    Args:
        data (dict[str, float]): 包含 ROI 名称及其对应值的字典。
        hemi (str, optional): 脑半球选择,支持 "lh"(左脑)或 "rh"(右脑)。默认为 "lh"。
        surf (str, optional): 大脑表面类型(如 "veryinflated", "midthickness")。默认为 "veryinflated"。
        atlas (str, optional): 使用的图谱名称,目前仅支持 "bna"。默认为 "bna"。
        vmin (Num, optional): 颜色映射的最小值。可以是整数或浮点数。默认为 None。
        vmax (Num, optional): 颜色映射的最大值。可以是整数或浮点数。默认为 None。
        cmap (str, optional): 颜色映射方案。默认为 "Reds"。
        colorbar (bool, optional): 是否显示颜色条。默认为 True。
        colorbar_location (str, optional): 颜色条的位置。默认为 "right"。
        colorbar_label_name (str, optional): 颜色条的标签名称。默认为空字符串。
        colorbar_label_rotation (int, optional): 颜色条标签的旋转角度。默认为 0。
        colorbar_decimals (int, optional): 颜色条刻度的小数位数。默认为 1。
        colorbar_fontsize (int, optional): 颜色条标签的字体大小。默认为 8。
        colorbar_nticks (int, optional): 颜色条上的刻度数量。默认为 2。
        colorbar_shrink (float, optional): 颜色条的缩放比例。默认为 0.15。
        colorbar_aspect (int, optional): 颜色条的宽高比。默认为 8。
        colorbar_draw_border (bool, optional): 是否绘制颜色条边框。默认为 False。
        title_name (str, optional): 图形标题。默认为空字符串。
        title_fontsize (int, optional): 标题字体大小。默认为 15。
        title_y (float, optional): 标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。

    Returns:
        plt.Figure: 返回一个 matplotlib 的 Figure 对象,表示生成的大脑表面图。
    """
    # 设置必要文件路径
    current_dir = op.dirname(__file__)
    neuromaps_data_dir = op.join(current_dir, "data/neurodata")
    if atlas == "bna":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/chimpanzee_BNA/ChimpBNA.L.32k_fs_LR.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/chimpanzee_BNA/ChimpBNA.R.32k_fs_LR.label.gii",
        )
        df = pd.read_csv(
            op.join(current_dir, "data/atlas_tables", "chimpanzee_bna.csv")
        )
    # 获取文件Underlay
    lh = op.join(
        neuromaps_data_dir,
        f"surfaces/chimpanzee_BNA/ChimpYerkes29_v1.2.L.{surf}.32k_fs_LR.surf.gii",
    )
    rh = op.join(
        neuromaps_data_dir,
        f"surfaces/chimpanzee_BNA/ChimpYerkes29_v1.2.R.{surf}.32k_fs_LR.surf.gii",
    )
    if hemi == "lh":
        p = Plot(lh, size=(800, 400), zoom=1.2)
    elif hemi == "rh":
        p = Plot(rh, size=(800, 400), zoom=1.2)
    # 将原始数据拆分成左右脑数据
    lh_data, rh_data = {}, {}
    for roi in data:
        if "lh_" in roi:
            lh_data[roi] = data[roi]
        elif "rh_" in roi:
            rh_data[roi] = data[roi]
    # 加载分区数据
    lh_roi_list, rh_roi_list = (
        list(df["ROIs_name"])[0 : int(len(df["ROIs_name"]) / 2)],
        list(df["ROIs_name"])[int(len(df["ROIs_name"]) / 2) : len(df["ROIs_name"])],
    )
    # 处理左脑数据
    lh_parc = nib.load(lh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in lh_roi_list}
    for vertex_index, label in enumerate(lh_parc):
        if label - 1 >= 0:
            roi_vertics[lh_roi_list[label - 1]].append(vertex_index)
    lh_parc = np.full(lh_parc.shape, np.nan)
    for roi in lh_data:
        lh_parc[roi_vertics[roi]] = lh_data[roi]
    # 处理右脑数据
    rh_parc = nib.load(rh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in rh_roi_list}
    for vertex_index, label in enumerate(rh_parc):
        if label - len(lh_roi_list) - 1 >= 0:
            roi_vertics[rh_roi_list[label - len(lh_roi_list) - 1]].append(vertex_index)
    rh_parc = np.full(rh_parc.shape, np.nan)
    for roi in rh_data:
        rh_parc[roi_vertics[roi]] = rh_data[roi]
    # 画图元素参数设置
    if vmin is None:
        vmin = min(data.values())
    if vmax is None:
        vmax = max(data.values())
    if vmin > vmax:
        print("vmin必须小于等于vmax")
        return
    if vmin == vmax:
        vmin = min(0, vmin)
        vmax = max(0, vmax)
    # colorbar参数设置
    colorbar_kws = {
        "location": colorbar_location,
        "label_direction": colorbar_label_rotation,
        "decimals": colorbar_decimals,
        "fontsize": colorbar_fontsize,
        "n_ticks": colorbar_nticks,
        "shrink": colorbar_shrink,
        "aspect": colorbar_aspect,
        "draw_border": colorbar_draw_border,
    }
    if hemi == "lh":
        p.add_layer(
            {"left": lh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )
    else:
        p.add_layer(
            {"left": rh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )  # 很怪,但是这里就是写“{'left': rh_parc}”
    fig = p.build(cbar_kws=colorbar_kws)
    fig.suptitle(title_name, fontsize=title_fontsize, y=title_y)
    return fig

plot_macaque_brain_figure

plot_macaque_brain_figure(data, surf='veryinflated', atlas='charm5', vmin=None, vmax=None, plot=True, cmap='Reds', colorbar=True, colorbar_location='right', colorbar_label_name='', colorbar_label_rotation=0, colorbar_decimals=1, colorbar_fontsize=8, colorbar_nticks=2, colorbar_shrink=0.15, colorbar_aspect=8, colorbar_draw_border=False, title_name='', title_fontsize=15, title_y=0.9, rjx_colorbar=False, rjx_colorbar_direction='vertical', horizontal_center=True, rjx_colorbar_outline=False, rjx_colorbar_label_name='', rjx_colorbar_tick_fontsize=10, rjx_colorbar_label_fontsize=10, rjx_colorbar_tick_rotation=0, rjx_colorbar_tick_length=0, rjx_colorbar_nticks=2)

绘制猕猴大脑表面图,支持多种图谱(CHARM5、CHARM6、BNA、D99)。

Parameters:

Name Type Description Default
data dict[str, float]

包含 ROI 名称及其对应值的字典。

required
surf str

大脑表面类型(如 "veryinflated", "inflated")。默认为 "veryinflated"。

'veryinflated'
atlas str

使用的图谱名称,支持 "charm5", "charm6", "bna", "d99"。默认为 "charm5"。

'charm5'
vmin Num

颜色映射的最小值。可以是整数或浮点数。默认为 None。

None
vmax Num

颜色映射的最大值。可以是整数或浮点数。默认为 None。

None
plot bool

是否直接绘制图形。默认为 True。

True
cmap str

颜色映射方案。默认为 "Reds"。

'Reds'
colorbar bool

是否显示颜色条。默认为 True。

True
colorbar_location str

颜色条的位置。默认为 "right"。

'right'
colorbar_label_name str

颜色条的标签名称。默认为空字符串。

''
colorbar_label_rotation int

颜色条标签的旋转角度。默认为 0。

0
colorbar_decimals int

颜色条刻度的小数位数。默认为 1。

1
colorbar_fontsize int

颜色条标签的字体大小。默认为 8。

8
colorbar_nticks int

颜色条上的刻度数量。默认为 2。

2
colorbar_shrink float

颜色条的缩放比例。默认为 0.15。

0.15
colorbar_aspect int

颜色条的宽高比。默认为 8。

8
colorbar_draw_border bool

是否绘制颜色条边框。默认为 False。

False
title_name str

图形标题。默认为空字符串。

''
title_fontsize int

标题字体大小。默认为 15。

15
title_y float

标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。

0.9
rjx_colorbar bool

是否使用自定义颜色条。默认为 False。

False
rjx_colorbar_direction str

自定义颜色条方向,支持 "vertical" 或 "horizontal"。默认为 "vertical"。

'vertical'
horizontal_center bool

水平颜色条是否居中。默认为 True。

True
rjx_colorbar_outline bool

自定义颜色条是否显示边框。默认为 False。

False
rjx_colorbar_label_name str

自定义颜色条标签名称。默认为空字符串。

''
rjx_colorbar_tick_fontsize int

自定义颜色条刻度字体大小。默认为 10。

10
rjx_colorbar_label_fontsize int

自定义颜色条标签字体大小。默认为 10。

10
rjx_colorbar_tick_rotation int

自定义颜色条刻度标签旋转角度。默认为 0。

0
rjx_colorbar_tick_length int

自定义颜色条刻度长度。默认为 0。

0
rjx_colorbar_nticks int

自定义颜色条上的刻度数量。默认为 2。

2

Returns:

Type Description
Figure | tuple[ndarray, ndarray]

Union[plt.Figure, tuple[np.ndarray, np.ndarray]]: 如果 plot=True,返回 matplotlib 的 Figure 对象;

Figure | tuple[ndarray, ndarray]

否则返回左右脑数据数组的元组 (lh_parc, rh_parc)

Source code in src/plotfig/brain_surface_deprecated.py
def plot_macaque_brain_figure(
    data: dict[str, float],
    surf: str = "veryinflated",
    atlas: str = "charm5",
    vmin: Num | None = None,
    vmax: Num | None = None,
    plot: bool = True,
    cmap: str = "Reds",
    colorbar: bool = True,
    colorbar_location: str = "right",
    colorbar_label_name: str = "",
    colorbar_label_rotation: int = 0,
    colorbar_decimals: int = 1,
    colorbar_fontsize: int = 8,
    colorbar_nticks: int = 2,
    colorbar_shrink: float = 0.15,
    colorbar_aspect: int = 8,
    colorbar_draw_border: bool = False,
    title_name: str = "",
    title_fontsize: int = 15,
    title_y: float = 0.9,
    rjx_colorbar: bool = False,
    rjx_colorbar_direction: str = "vertical",
    horizontal_center: bool = True,
    rjx_colorbar_outline: bool = False,
    rjx_colorbar_label_name: str = "",
    rjx_colorbar_tick_fontsize: int = 10,
    rjx_colorbar_label_fontsize: int = 10,
    rjx_colorbar_tick_rotation: int = 0,
    rjx_colorbar_tick_length: int = 0,
    rjx_colorbar_nticks: int = 2,
) -> plt.Figure | tuple[np.ndarray, np.ndarray]:
    """
    绘制猕猴大脑表面图,支持多种图谱(CHARM5、CHARM6、BNA、D99)。

    Args:
        data (dict[str, float]): 包含 ROI 名称及其对应值的字典。
        surf (str, optional): 大脑表面类型(如 "veryinflated", "inflated")。默认为 "veryinflated"。
        atlas (str, optional): 使用的图谱名称,支持 "charm5", "charm6", "bna", "d99"。默认为 "charm5"。
        vmin (Num, optional): 颜色映射的最小值。可以是整数或浮点数。默认为 None。
        vmax (Num, optional): 颜色映射的最大值。可以是整数或浮点数。默认为 None。
        plot (bool, optional): 是否直接绘制图形。默认为 True。
        cmap (str, optional): 颜色映射方案。默认为 "Reds"。
        colorbar (bool, optional): 是否显示颜色条。默认为 True。
        colorbar_location (str, optional): 颜色条的位置。默认为 "right"。
        colorbar_label_name (str, optional): 颜色条的标签名称。默认为空字符串。
        colorbar_label_rotation (int, optional): 颜色条标签的旋转角度。默认为 0。
        colorbar_decimals (int, optional): 颜色条刻度的小数位数。默认为 1。
        colorbar_fontsize (int, optional): 颜色条标签的字体大小。默认为 8。
        colorbar_nticks (int, optional): 颜色条上的刻度数量。默认为 2。
        colorbar_shrink (float, optional): 颜色条的缩放比例。默认为 0.15。
        colorbar_aspect (int, optional): 颜色条的宽高比。默认为 8。
        colorbar_draw_border (bool, optional): 是否绘制颜色条边框。默认为 False。
        title_name (str, optional): 图形标题。默认为空字符串。
        title_fontsize (int, optional): 标题字体大小。默认为 15。
        title_y (float, optional): 标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。
        rjx_colorbar (bool, optional): 是否使用自定义颜色条。默认为 False。
        rjx_colorbar_direction (str, optional): 自定义颜色条方向,支持 "vertical" 或 "horizontal"。默认为 "vertical"。
        horizontal_center (bool, optional): 水平颜色条是否居中。默认为 True。
        rjx_colorbar_outline (bool, optional): 自定义颜色条是否显示边框。默认为 False。
        rjx_colorbar_label_name (str, optional): 自定义颜色条标签名称。默认为空字符串。
        rjx_colorbar_tick_fontsize (int, optional): 自定义颜色条刻度字体大小。默认为 10。
        rjx_colorbar_label_fontsize (int, optional): 自定义颜色条标签字体大小。默认为 10。
        rjx_colorbar_tick_rotation (int, optional): 自定义颜色条刻度标签旋转角度。默认为 0。
        rjx_colorbar_tick_length (int, optional): 自定义颜色条刻度长度。默认为 0。
        rjx_colorbar_nticks (int, optional): 自定义颜色条上的刻度数量。默认为 2。

    Returns:
        Union[plt.Figure, tuple[np.ndarray, np.ndarray]]: 如果 `plot=True`,返回 matplotlib 的 Figure 对象;
        否则返回左右脑数据数组的元组 `(lh_parc, rh_parc)`。
    """
    # 设置必要文件路径
    current_dir = op.dirname(__file__)
    neuromaps_data_dir = op.join(current_dir, "data/neurodata")
    if atlas == "charm5":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM5/L.charm5.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM5/R.charm5.label.gii",
        )
        df = pd.read_csv(
            op.join(current_dir, "data/atlas_tables", "macaque_charm5.csv")
        )
    elif atlas == "charm6":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM6/L.charm6.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM6/R.charm6.label.gii",
        )
        df = pd.read_csv(
            op.join(current_dir, "data/atlas_tables", "macaque_charm6.csv")
        )
    elif atlas == "bna":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_BNA/L.charm5.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_BNA/R.charm5.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables", "macaque_bna.csv"))
    elif atlas == "d99":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_D99/L.d99.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_D99/R.d99.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables", "macaque_d99.csv"))
    # 获取文件Underlay
    lh = op.join(
        neuromaps_data_dir, f"surfaces/macaque_BNA/civm.L.{surf}.32k_fs_LR.surf.gii"
    )
    rh = op.join(
        neuromaps_data_dir, f"surfaces/macaque_BNA/civm.R.{surf}.32k_fs_LR.surf.gii"
    )
    p = Plot(lh, rh)
    # 将原始数据拆分成左右脑数据
    lh_data, rh_data = {}, {}
    for roi in data:
        if "lh_" in roi:
            lh_data[roi] = data[roi]
        elif "rh_" in roi:
            rh_data[roi] = data[roi]
    # 加载图集分区数据
    lh_roi_list, rh_roi_list = (
        list(df["ROIs_name"])[0 : int(len(df["ROIs_name"]) / 2)],
        list(df["ROIs_name"])[int(len(df["ROIs_name"]) / 2) : len(df["ROIs_name"])],
    )
    # 处理左脑数据
    lh_parc = nib.load(lh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in lh_roi_list}
    for vertex_index, label in enumerate(lh_parc):
        if label - 1 >= 0:
            roi_vertics[lh_roi_list[label - 1]].append(vertex_index)
    lh_parc = np.full(lh_parc.shape, np.nan)
    for roi in lh_data:
        lh_parc[roi_vertics[roi]] = lh_data[roi]
    # 处理右脑数据
    rh_parc = nib.load(rh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in rh_roi_list}
    for vertex_index, label in enumerate(rh_parc):
        if label - 1 - len(lh_roi_list) >= 0:
            roi_vertics[rh_roi_list[label - 1 - len(lh_roi_list)]].append(vertex_index)
    rh_parc = np.full(rh_parc.shape, np.nan)
    for roi in rh_data:
        rh_parc[roi_vertics[roi]] = rh_data[roi]
    # 画图
    if plot:
        # 画图元素参数设置
        if vmin is None:
            vmin = min(data.values())
        if vmax is None:
            vmax = max(data.values())
        if vmin > vmax:
            print("vmin必须小于等于vmax")
            return
        if vmin == vmax:
            vmin = min(0, vmin)
            vmax = max(0, vmax)
        # colorbar参数设置
        colorbar_kws = {
            "location": colorbar_location,
            "label_direction": colorbar_label_rotation,
            "decimals": colorbar_decimals,
            "fontsize": colorbar_fontsize,
            "n_ticks": colorbar_nticks,
            "shrink": colorbar_shrink,
            "aspect": colorbar_aspect,
            "draw_border": colorbar_draw_border,
        }
        p.add_layer(
            {"left": lh_parc, "right": rh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )
        fig = p.build(cbar_kws=colorbar_kws)
        fig.suptitle(title_name, fontsize=title_fontsize, y=title_y)
        ############################################### rjx_colorbar ###############################################
        sm = ScalarMappable(cmap=cmap)
        sm.set_array((vmin, vmax))  # 设置值范围
        if rjx_colorbar:
            formatter = ScalarFormatter(useMathText=True)  # 科学计数法相关
            formatter.set_powerlimits(
                (-3, 3)
            )  # <=-1也就是小于等于0.1,>=2,也就是大于等于100,会写成科学计数法
            if rjx_colorbar_direction == "vertical":
                cax = fig.add_axes(
                    [1, 0.425, 0.01, 0.15]
                )  # [left, bottom, width, height]
                cbar = fig.colorbar(
                    sm, cax=cax, orientation="vertical", cmap=cmap
                )  # "vertical", "horizontal"
                cbar.outline.set_visible(rjx_colorbar_outline)
                cbar.ax.set_ylabel(
                    rjx_colorbar_label_name, fontsize=rjx_colorbar_label_fontsize
                )
                cbar.ax.yaxis.set_label_position(
                    "left"
                )  # 原本设置y轴label默认在右边,现在换到左边
                cbar.ax.tick_params(
                    axis="y",
                    which="major",
                    labelsize=rjx_colorbar_tick_fontsize,
                    rotation=rjx_colorbar_tick_rotation,
                    length=rjx_colorbar_tick_length,
                )
                cbar.set_ticks(np.linspace(vmin, vmax, rjx_colorbar_nticks))
                if vmax < 0.001 or vmax > 1000:  # y轴设置科学计数法
                    cbar.ax.yaxis.set_major_formatter(formatter)
                    cbar.ax.yaxis.get_offset_text().set_visible(
                        False
                    )  # 隐藏默认的偏移文本
                    exponent = math.floor(math.log10(vmax))
                    # 手动添加文本
                    cbar.ax.text(
                        1.05,
                        1.15,
                        rf"$\times 10^{{{exponent}}}$",
                        transform=cbar.ax.transAxes,
                        fontsize=rjx_colorbar_tick_fontsize,
                        verticalalignment="bottom",
                        horizontalalignment="left",
                    )
            elif rjx_colorbar_direction == "horizontal":
                if horizontal_center:
                    cax = fig.add_axes([0.44, 0.5, 0.15, 0.01])
                else:
                    cax = fig.add_axes([0.44, 0.05, 0.15, 0.01])
                cbar = fig.colorbar(sm, cax=cax, orientation="horizontal", cmap=cmap)
                cbar.outline.set_visible(rjx_colorbar_outline)
                cbar.ax.set_title(
                    rjx_colorbar_label_name, fontsize=rjx_colorbar_label_fontsize
                )
                cbar.ax.tick_params(
                    axis="x",
                    which="major",
                    labelsize=rjx_colorbar_tick_fontsize,
                    rotation=rjx_colorbar_tick_rotation,
                    length=rjx_colorbar_tick_length,
                )
                if vmax < 0.001 or vmax > 1000:  # y轴设置科学计数法
                    cbar.ax.xaxis.set_major_formatter(formatter)
            cbar.set_ticks([vmin, vmax])
            ########################################### rjx_colorbar ###############################################
        return fig
    return lh_parc, rh_parc

plot_macaque_hemi_brain_figure

plot_macaque_hemi_brain_figure(data, hemi='lh', surf='veryinflated', atlas='charm5', vmin=None, vmax=None, cmap='Reds', colorbar=True, colorbar_location='right', colorbar_label_name='', colorbar_label_rotation=0, colorbar_decimals=1, colorbar_fontsize=8, colorbar_nticks=2, colorbar_shrink=0.15, colorbar_aspect=8, colorbar_draw_border=False, title_name='', title_fontsize=15, title_y=0.9)
Source code in src/plotfig/brain_surface_deprecated.py
def plot_macaque_hemi_brain_figure(
    data: dict[str, float],
    hemi: str = "lh",
    surf: str = "veryinflated",
    atlas: str = "charm5",
    vmin: Num | None = None,
    vmax: Num | None = None,
    cmap: str = "Reds",
    colorbar: bool = True,
    colorbar_location: str = "right",
    colorbar_label_name: str = "",
    colorbar_label_rotation: int = 0,
    colorbar_decimals: int = 1,
    colorbar_fontsize: int = 8,
    colorbar_nticks: int = 2,
    colorbar_shrink: float = 0.15,
    colorbar_aspect: int = 8,
    colorbar_draw_border: bool = False,
    title_name: str = "",
    title_fontsize: int = 15,
    title_y: float = 0.9,
) -> plt.Figure | None:
    warnings.warn(
        "plot_macaque_hemi_brain_figure 即将弃用,请使用 plot_brain_surface_figure 替代。未来版本将移除本函数。",
        DeprecationWarning,
        stacklevel=2
    )
    """
    绘制猕猴大脑单侧(左脑或右脑)表面图,支持多种图谱(CHARM5、CHARM6、BNA、D99)。

    Args:
        data (dict[str, float]): 包含 ROI 名称及其对应值的字典。
        hemi (str, optional): 脑半球选择,支持 "lh"(左脑)或 "rh"(右脑)。默认为 "lh"。
        surf (str, optional): 大脑表面类型(如 "veryinflated", "inflated")。默认为 "veryinflated"。
        atlas (str, optional): 使用的图谱名称,支持 "charm5", "charm6", "bna", "d99"。默认为 "charm5"。
        vmin (Num, optional): 颜色映射的最小值。可以是整数或浮点数。默认为 None。
        vmax (Num, optional): 颜色映射的最大值。可以是整数或浮点数。默认为 None。
        cmap (str, optional): 颜色映射方案。默认为 "Reds"。
        colorbar (bool, optional): 是否显示颜色条。默认为 True。
        colorbar_location (str, optional): 颜色条的位置。默认为 "right"。
        colorbar_label_name (str, optional): 颜色条的标签名称。默认为空字符串。
        colorbar_label_rotation (int, optional): 颜色条标签的旋转角度。默认为 0。
        colorbar_decimals (int, optional): 颜色条刻度的小数位数。默认为 1。
        colorbar_fontsize (int, optional): 颜色条标签的字体大小。默认为 8。
        colorbar_nticks (int, optional): 颜色条上的刻度数量。默认为 2。
        colorbar_shrink (float, optional): 颜色条的缩放比例。默认为 0.15。
        colorbar_aspect (int, optional): 颜色条的宽高比。默认为 8。
        colorbar_draw_border (bool, optional): 是否绘制颜色条边框。默认为 False。
        title_name (str, optional): 图形标题。默认为空字符串。
        title_fontsize (int, optional): 标题字体大小。默认为 15。
        title_y (float, optional): 标题在 y 轴上的位置(范围通常为 0~1)。默认为 0.9。

    Returns:
        plt.Figure: 返回一个 matplotlib 的 Figure 对象,表示生成的大脑表面图。
    """

    # 设置必要文件路径
    current_dir = op.dirname(__file__)
    neuromaps_data_dir = op.join(current_dir, "data/neurodata")
    if atlas == "charm5":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM5/L.charm5.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM5/R.charm5.label.gii",
        )
        df = pd.read_csv(
            op.join(current_dir, "data/atlas_tables", "macaque_charm5.csv")
        )
    elif atlas == "charm6":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM6/L.charm6.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_CHARM6/R.charm6.label.gii",
        )
        df = pd.read_csv(
            op.join(current_dir, "data/atlas_tables", "macaque_charm6.csv")
        )
    elif atlas == "bna":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_BNA/L.charm5.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_BNA/R.charm5.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables", "macaque_bna.csv"))
    elif atlas == "d99":
        lh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_D99/L.d99.label.gii",
        )
        rh_atlas_dir = op.join(
            neuromaps_data_dir,
            "atlases/macaque_D99/R.d99.label.gii",
        )
        df = pd.read_csv(op.join(current_dir, "data/atlas_tables", "macaque_d99.csv"))
    # 获取文件Underlay
    lh = op.join(
        neuromaps_data_dir, f"surfaces/macaque_BNA/civm.L.{surf}.32k_fs_LR.surf.gii"
    )
    rh = op.join(
        neuromaps_data_dir, f"surfaces/macaque_BNA/civm.R.{surf}.32k_fs_LR.surf.gii"
    )
    if hemi == "lh":
        p = Plot(lh, size=(800, 400), zoom=1.2)
    elif hemi == "rh":
        p = Plot(rh, size=(800, 400), zoom=1.2)
    # 将原始数据拆分成左右脑数据
    lh_data, rh_data = {}, {}
    for roi in data:
        if "lh_" in roi:
            lh_data[roi] = data[roi]
        elif "rh_" in roi:
            rh_data[roi] = data[roi]
    # 加载分区数据
    lh_roi_list, rh_roi_list = (
        list(df["ROIs_name"])[0 : int(len(df["ROIs_name"]) / 2)],
        list(df["ROIs_name"])[int(len(df["ROIs_name"]) / 2) : len(df["ROIs_name"])],
    )
    # 处理左脑数据
    lh_parc = nib.load(lh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in lh_roi_list}
    for vertex_index, label in enumerate(lh_parc):
        if label - 1 >= 0:
            roi_vertics[lh_roi_list[label - 1]].append(vertex_index)
    lh_parc = np.full(lh_parc.shape, np.nan)
    for roi in lh_data:
        lh_parc[roi_vertics[roi]] = lh_data[roi]
    # 处理右脑数据
    rh_parc = nib.load(rh_atlas_dir).darrays[0].data
    roi_vertics = {roi: [] for roi in rh_roi_list}
    for vertex_index, label in enumerate(rh_parc):
        if label - len(lh_roi_list) - 1 >= 0:
            roi_vertics[rh_roi_list[label - len(lh_roi_list) - 1]].append(vertex_index)
    rh_parc = np.full(rh_parc.shape, np.nan)
    for roi in rh_data:
        rh_parc[roi_vertics[roi]] = rh_data[roi]
    # 画图元素参数设置
    if vmin is None:
        vmin = min(data.values())
    if vmax is None:
        vmax = max(data.values())
    if vmin > vmax:
        print("vmin必须小于等于vmax")
        return
    if vmin == vmax:
        vmin = min(0, vmin)
        vmax = max(0, vmax)
    # colorbar参数设置
    colorbar_kws = {
        "location": colorbar_location,
        "label_direction": colorbar_label_rotation,
        "decimals": colorbar_decimals,
        "fontsize": colorbar_fontsize,
        "n_ticks": colorbar_nticks,
        "shrink": colorbar_shrink,
        "aspect": colorbar_aspect,
        "draw_border": colorbar_draw_border,
    }
    if hemi == "lh":
        p.add_layer(
            {"left": lh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )
    else:
        p.add_layer(
            {"left": rh_parc},
            cbar=colorbar,
            cmap=cmap,
            color_range=(vmin, vmax),
            cbar_label=colorbar_label_name,
            zero_transparent=False,
        )  # 很怪,但是这里就是写“{'left': rh_parc}”
    fig = p.build(cbar_kws=colorbar_kws)
    fig.suptitle(title_name, fontsize=title_fontsize, y=title_y)
    return fig

plotfig.brain_connection

plot_brain_connection_figure

plot_brain_connection_figure(connectome, lh_surfgii_file, rh_surfgii_file, niigz_file, output_file=None, show_all_nodes=False, nodes_size=None, nodes_name=None, nodes_color=None, scale_method='', line_width=10, line_color='red')

绘制大脑连接图,保存在指定的html文件中

Parameters:

Name Type Description Default
connectome NDArray

大脑连接矩阵,形状为 (n, n),其中 n 是脑区数量。 矩阵中的值表示脑区之间的连接强度,正值表示正相关连接,负值表示负相关连接,0表示无连接。

required
lh_surfgii_file str | Path

左半脑表面几何文件路径 (.surf.gii 格式),用于绘制左半脑表面

required
rh_surfgii_file str | Path

右半脑表面几何文件路径 (.surf.gii 格式),用于绘制右半脑表面

required
niigz_file str | Path

NIfTI格式的脑区图谱文件路径 (.nii.gz 格式),用于定位脑区节点的三维坐标

required
output_file str | Path | None

输出HTML文件路径。如果未指定,则使用当前时间戳生成文件名。默认为None

None
show_all_nodes bool

是否显示所有脑区节点。如果为False,则只显示有连接的节点。默认为False

False
nodes_size Sequence[Num] | NDArray | None

每个节点的大小,长度应与脑区数量一致。默认为None,即所有节点大小为5

None
nodes_name list[str] | None

每个节点的名称标签,长度应与脑区数量一致。默认为None,即不显示名称

None
nodes_color list[str] | None

每个节点的颜色,长度应与脑区数量一致。默认为None,即所有节点为白色

None
scale_method Literal['', 'width', 'color', 'width_color', 'color_width']

连接线的缩放方法: - "" : 所有连接线宽度和颜色固定 - "width" : 根据连接强度调整线宽,正连接为红色,负连接为蓝色 - "color" : 根据连接强度调整颜色(使用蓝白红颜色映射),线宽固定 - "width_color" or "color_width" : 同时根据连接强度调整线宽和颜色 默认为 ""

''
line_width Num

连接线的基本宽度。当scale_method包含"width"时,此值作为最大宽度参考。默认为10

10
line_color str

连接线的基本颜色。当scale_method不包含"color"时生效。默认为"#ff0000"(红色)

'red'

Returns:

Type Description
Figure

go.Figure: Plotly图形对象,包含绘制的大脑连接图

Source code in src/plotfig/brain_connection.py
def plot_brain_connection_figure(
    connectome: npt.NDArray,
    lh_surfgii_file: str | Path,
    rh_surfgii_file: str | Path,
    niigz_file: str | Path,
    output_file: str | Path | None = None,
    show_all_nodes: bool = False,
    nodes_size: Sequence[Num] | npt.NDArray | None = None,
    nodes_name: list[str] | None = None,
    nodes_color: list[str] | None = None,
    scale_method: Literal["", "width", "color", "width_color", "color_width"] = "",
    line_width: Num = 10,
    line_color: str = "red",
) -> go.Figure:
    """绘制大脑连接图,保存在指定的html文件中

    Args:
        connectome (npt.NDArray):
            大脑连接矩阵,形状为 (n, n),其中 n 是脑区数量。
            矩阵中的值表示脑区之间的连接强度,正值表示正相关连接,负值表示负相关连接,0表示无连接。
        lh_surfgii_file (str | Path):
            左半脑表面几何文件路径 (.surf.gii 格式),用于绘制左半脑表面
        rh_surfgii_file (str | Path):
            右半脑表面几何文件路径 (.surf.gii 格式),用于绘制右半脑表面
        niigz_file (str | Path):
            NIfTI格式的脑区图谱文件路径 (.nii.gz 格式),用于定位脑区节点的三维坐标
        output_file (str | Path | None, optional):
            输出HTML文件路径。如果未指定,则使用当前时间戳生成文件名。默认为None
        show_all_nodes (bool, optional):
            是否显示所有脑区节点。如果为False,则只显示有连接的节点。默认为False
        nodes_size (Sequence[Num] | npt.NDArray | None, optional):
            每个节点的大小,长度应与脑区数量一致。默认为None,即所有节点大小为5
        nodes_name (list[str] | None, optional):
            每个节点的名称标签,长度应与脑区数量一致。默认为None,即不显示名称
        nodes_color (list[str] | None, optional):
            每个节点的颜色,长度应与脑区数量一致。默认为None,即所有节点为白色
        scale_method (Literal["", "width", "color", "width_color", "color_width"], optional):
            连接线的缩放方法:
            - "" : 所有连接线宽度和颜色固定
            - "width" : 根据连接强度调整线宽,正连接为红色,负连接为蓝色
            - "color" : 根据连接强度调整颜色(使用蓝白红颜色映射),线宽固定
            - "width_color" or "color_width" : 同时根据连接强度调整线宽和颜色
            默认为 ""
        line_width (Num, optional):
            连接线的基本宽度。当scale_method包含"width"时,此值作为最大宽度参考。默认为10
        line_color (str, optional):
            连接线的基本颜色。当scale_method不包含"color"时生效。默认为"#ff0000"(红色)

    Returns:
        go.Figure: Plotly图形对象,包含绘制的大脑连接图
    """
    _validate_connectome(connectome)

    if np.any(connectome < 0):
        logger.warning(
            "由于 connectome 存在负值,连线颜色无法自定义,只能正值显示红色,负值显示蓝色"
        )
        line_color = "#ff0000"

    nodes_num = connectome.shape[0]
    nodes_name = nodes_name or [""] * nodes_num
    nodes_color = nodes_color or ["white"] * nodes_num
    nodes_size = nodes_size or [5] * nodes_num

    if output_file is None:
        timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
        output_file = Path(f"{timestamp}.html")
        logger.info(f"未指定保存路径,默认保存在当前文件夹下的{output_file}中。")

    node_indices = _get_node_indices(connectome, show_all_nodes)
    vertices_L, faces_L = _load_surface(lh_surfgii_file)
    vertices_R, faces_R = _load_surface(rh_surfgii_file)

    mesh_L = _create_mesh(vertices_L, faces_L, "Left Hemisphere")
    mesh_R = _create_mesh(vertices_R, faces_R, "Right Hemisphere")

    fig = go.Figure(data=[mesh_L, mesh_R])

    centroids_real = _get_centroids_real(niigz_file)
    _add_nodes_to_fig(
        fig, centroids_real, node_indices, nodes_name, nodes_size, nodes_color
    )
    _add_edges_to_fig(
        fig,
        connectome,
        centroids_real,
        nodes_name,
        scale_method,
        line_width,
        line_color,
    )
    _finalize_figure(fig)

    fig.write_html(output_file)
    return fig

save_brain_connection_frames

save_brain_connection_frames(fig, output_dir, n_frames=36)

生成不同角度的静态图片帧,可用于制作旋转大脑连接图的 GIF。

Parameters:

Name Type Description Default
fig Figure

Plotly 的 Figure 对象,包含大脑表面和连接图。

required
output_dir str

图片保存的文件夹路径,若文件夹不存在则自动创建。

required
n_frames int

旋转帧的数量。默认 36,即每 10 度一帧。

36
Source code in src/plotfig/brain_connection.py
def save_brain_connection_frames(
    fig: go.Figure, output_dir: str | Path, n_frames: int = 36
) -> None:
    """
    生成不同角度的静态图片帧,可用于制作旋转大脑连接图的 GIF。

    Args:
        fig (go.Figure): Plotly 的 Figure 对象,包含大脑表面和连接图。
        output_dir (str): 图片保存的文件夹路径,若文件夹不存在则自动创建。
        n_frames (int, optional): 旋转帧的数量。默认 36,即每 10 度一帧。
    """
    Path(output_dir).mkdir(parents=True, exist_ok=True)
    angles = np.linspace(0, 360, n_frames, endpoint=False)
    for i, angle in tqdm(enumerate(angles), total=len(angles)):
        camera = dict(
            eye=dict(
                x=2 * np.cos(np.radians(angle)), y=2 * np.sin(np.radians(angle)), z=0.7
            )
        )
        fig.update_layout(scene_camera=camera)
        pio.write_image(fig, f"{output_dir}/frame_{i:03d}.png", width=800, height=800)
    logger.info(f"保存了 {n_frames} 张图片在 {output_dir}")