【Brain Connectivity Toolbox】大脑连接图谱:图度计算总结

零、写在前面

这篇博客总结了Brain Connectivity Toolbox中关于计算图的相关的方法。
包括:

  • 有向图
    • 有向图中节点的入度、出度和度数
    • 有向图中节点的强度(出强度、入强度)
  • 无向图
    • 无向图中节点的度数
    • 无向图中节点的强度(区分正权重和负权重的边)
  • 联合度矩阵(网络中节点的度分布特性的矩阵)

一、有向图

1. 计算有向图中节点的入度、出度和度数

在有向图中,节点的度数为入度 + 出度。

代码实现

import numpy as np

def degrees_dir(CIJ):
    '''
    计算有向图中节点的入度、出度和度数。
    
    参数:
    ----------
    CIJ : NxN numpy.ndarray
        有向图的邻接矩阵,可以是二进制或带权重的。

    返回:
    -------
    id : Nx1 numpy.ndarray
        节点的入度数组。
    od : Nx1 numpy.ndarray
        节点的出度数组。
    deg : Nx1 numpy.ndarray
        节点的度数数组(入度 + 出度)。

    注意:
    -----
    输入的CIJ矩阵的列代表节点,权重信息将被忽略。
    '''

    # 确保CIJ矩阵是二进制的,如果CIJ不是二进制的,将进行转换
    CIJ = binarize(CIJ, copy=True)  
    
    # 计算入度:CIJ矩阵的每列求和,得到节点的入度
    id = np.sum(CIJ, axis=0)  
    
    # 计算出度:CIJ矩阵的每行求和,得到节点的出度
    od = np.sum(CIJ, axis=1)  
    
    # 计算度数:入度加上出度
    deg = id + od  
    
    return id, od, deg
# 使用实例:
# 假设我们有一个3x3的有向图邻接矩阵,其中1表示存在边,0表示不存在边
CIJ_example = np.array([
    [0, 1, 0],  # 节点0没有出边,节点1有一个入边
    [0, 0, 1],  # 节点1有一个出边到节点2
    [1, 0, 0]   # 节点2有一个入边从节点0
])

# 调用degrees_dir函数计算入度、出度和度数
in_degrees, out_degrees, degrees = degrees_dir(CIJ_example)

# 打印结果
print("In-degrees:", in_degrees)  # 入度	array([1, 1, 1])
print("Out-degrees:", out_degrees)  # 出度	array([1, 1, 1])
print("Degrees:", degrees)  # 度数	array([2, 2, 2])

2. 计算有向图中节点的强度

入强度是指向该节点的边权重之和(axis=0)
出强度是从此节点出发的边权重之和(axis=1)

代码实现

import numpy as np

def strengths_dir(CIJ):
    '''
    计算有向图中节点的强度。节点的强度是与节点相连的边的权重之和。
    入强度是指向该节点的边权重之和,出强度是从此节点出发的边权重之和。

    参数:
    ----------
    CIJ : NxN np.ndarray
        有向图的加权邻接矩阵

    返回:
    -------
    is : Nx1 np.ndarray
        节点的入强度数组
    os : Nx1 np.ndarray
        节点的出强度数组
    str : Nx1 np.ndarray
        节点的强度数组(入强度 + 出强度)

    注意:
    -----
    输入的CIJ矩阵的列代表节点。
    '''
    # 计算入强度:CIJ矩阵的每列求和,得到每个节点的入强度
    istr = np.sum(CIJ, axis=0)  
    
    # 计算出强度:CIJ矩阵的每行求和,得到每个节点的出强度
    ostr = np.sum(CIJ, axis=1)  
    
    # 计算节点的总强度:入强度加上出强度
    return istr + ostr
# 使用实例:
# 假设我们有一个3x3的有向图邻接矩阵,权重表示边的权重
CIJ_example = np.array([
    [0, 1, 0],  # 节点0没有出边,但有1条边从节点1指向它,权重为1
    [0, 0, 2],  # 节点1没有出边,但有1条边从节点2指向它,权重为2
    [3, 0, 0]   # 节点2有1条出边到节点0,权重为3
])

# 调用strengths_dir函数计算节点的强度
strengths = strengths_dir(CIJ_example)

# 打印结果
print("In-strengths of each node:", strengths[0])  # 入强度
print("Out-strengths of each node:", strengths[1])  # 出强度
print("Total strengths of each node:", strengths[2])  # 总强度

二、无向图

1. 计算无向图中节点的度数

在无向图中,节点的度数是与节点相连的边的数量。

代码实现

import numpy as np

def degrees_und(CIJ):
    '''
    计算无向图中节点的度数。节点的度数是与节点相连的边的数量。

    参数:
    ----------
    CIJ : NxN np.ndarray
        无向图的邻接矩阵,可以是二进制或带权重的。

    返回:
    -------
    deg : Nx1 np.ndarray
        节点的度数数组。

    注意:
    -----
    权重信息将被忽略,只考虑边的存在。
    '''
    # 确保CIJ矩阵是二进制的,如果CIJ不是二进制的,将进行转换
    CIJ = binarize(CIJ, copy=True)  
    
    # 计算度数:对于无向图,度数是CIJ矩阵每一行(或每一列,因为图是无向的)
    # 元素的总和,这里使用axis=0来计算每列的和,也就是每个节点的度数
    return np.sum(CIJ, axis=0)
# 使用实例:
# 假设我们有一个3x3的无向图邻接矩阵,其中1表示存在边,0表示不存在边
CIJ_example = np.array([
    [0, 1, 1],  # 节点0与节点1和节点2相连
    [1, 0, 1],  # 节点1与节点0和节点2相连
    [1, 1, 0]   # 节点2与节点0和节点1相连
])

# 调用degrees_und函数计算节点的度数
degrees = degrees_und(CIJ_example)	# array([2, 2, 2])
# 打印结果
print("Degrees of each node:", degrees)

2. 计算无向图中节点的强度

在无向图中,节点的强度是与节点相连的所有边的权重之和。

代码实现

import numpy as np

def strengths_und(CIJ):
    '''
    计算无向图中节点的强度。节点的强度是与节点相连的所有边的权重之和。

    参数:
    ----------
    CIJ : NxN np.ndarray
        无向图的加权邻接矩阵

    返回:
    -------
    str : Nx1 np.ndarray
        节点的强度数组
    '''
    # 计算节点的强度:对于无向图,节点的强度等于CIJ矩阵每一列(或行,因为图是无向的)
    # 的元素权重之和。这里使用axis=0来计算每列的和,也就是每个节点的强度
    return np.sum(CIJ, axis=0)
# 使用实例:
# 假设我们有一个3x3的无向图邻接矩阵,权重表示边的权重
CIJ_example = np.array([
    [0, 2, 1],  # 节点0与节点1相连的边权重为2,与节点2相连的边权重为1
    [2, 0, 3],  # 节点1与节点0相连的边权重为2,与节点2相连的边权重为3
    [1, 3, 0]   # 节点2与节点0相连的边权重为1,与节点1相连的边权重为3
])

# 调用strengths_und函数计算节点的强度
node_strengths = strengths_und(CIJ_example)

# 打印结果
print("Strengths of each node:", node_strengths)

3. 计算无向图中节点的强度,区分正权重和负权重的边

import numpy as np

def strengths_und_sign(W):
    '''
    计算无向图中节点的强度,区分正权重和负权重的边。

    参数:
    ----------
    W : NxN np.ndarray
        无向连接矩阵,包含正权重和负权重的边

    返回:
    -------
    Spos : Nx1 np.ndarray
        正权重边的节点强度数组
    Sneg : Nx1 np.ndarray
        负权重边的节点强度数组
    vpos : float
        正权重边的总权重
    vneg : float
        负权重边的总权重
    '''
    W = W.copy()  # 复制W矩阵,避免修改原始矩阵
    n = len(W)  # 矩阵的大小,即节点的数量
    np.fill_diagonal(W, 0)  # 将对角线元素设为0,因为自环没有权重

    # 计算正权重边的节点强度:W中元素大于0的条件下的元素乘积后求和,对每列进行操作
    Spos = np.sum(W * (W > 0), axis=0)  
    
    # 计算负权重边的节点强度:W中元素小于0的条件下的元素乘积后求和,对每列进行操作
    Sneg = np.sum(W * (W < 0), axis=0) 

    # 计算总的正权重:W中所有大于0的元素的总和
    vpos = np.sum(W[W > 0])  
    
    # 计算总的负权重:W中所有小于0的元素的总和
    vneg = np.sum(W[W < 0])  
    
    return Spos, Sneg, vpos, vneg
# 使用实例:
# 假设我们有一个3x3的无向图加权邻接矩阵,权重可以是正数或负数
W_example = np.array([
    [0,  2, -1],  # 节点0与节点1相连的边权重为2,与节点2相连的边权重为-1
    [2,  0,  3],  # 节点1与节点0相连的边权重为2,与节点2相连的边权重为3
    [-1, 3,  0]   # 节点2与节点0相连的边权重为-1,与节点1相连的边权重为3
])

# 调用strengths_und_sign函数计算正负权重的节点强度和总权重
positive_strengths, negative_strengths, total_positive_weight, total_negative_weight = strengths_und_sign(W_example)

# 打印结果
print("Positive strengths of each node:", positive_strengths)		
# array([2, 5, 3])
print("Negative strengths of each node:", negative_strengths)
# array([-1,  0, -1])
print("Total positive weight:", total_positive_weight)
# 10
print("Total negative weight:", total_negative_weight)
# -2

其他

1. 将输入的带权重的连接矩阵转换为二进制矩阵

def binarize(W, copy=True):
    '''
    将输入的带权重的连接矩阵转换为二进制矩阵。如果copy参数没有设置,这个函数将就地修改W。

    参数:
    ----------
    W : NxN np.ndarray
        带权重的连接矩阵。
    copy : bool
        如果为True,则返回矩阵的副本。否则,将就地修改矩阵。默认值为True。

    返回:
    -------
    W : NxN np.ndarray
        二进制连接矩阵。
    '''
    if copy:  # 如果copy参数为True,则复制W矩阵
        W = W.copy()  # 复制W矩阵,以避免就地修改原始数据
    # 将W矩阵中所有非零元素设置为1,实现二值化
    W[W != 0] = 1
    return W  # 返回修改后的二进制矩阵

2. 计算联合度矩阵

什么是联合度矩阵

联合度矩阵(Joint Degree Matrix)是一个用来表示网络中节点的度(Degree)分布特性的矩阵,特别是在有向图中,它同时考虑了节点的入度(In-degree)和出度(Out-degree)。这个矩阵可以揭示网络的结构特性,比如节点的连接模式和网络的中心性分布。

如何计算联合度矩阵

可以按照以下步骤计算联合度矩阵:

  1. 计算每个节点的入度和出度

    • 入度是指有多少条边指向该节点。
    • 出度是指有多少条边从该节点发出。
  2. 构建联合度矩阵

    • 联合度矩阵的元素 ( JDM(i, j) ) 表示出度为 ( i ) 且入度为 ( j ) 的节点对的数量。

代码实现

def jdegree(CIJ):
    '''
    该函数返回一个矩阵,其中每个元素 (u,v) 对应的值表示具有 u 个出边和 v 个入边的节点数量。

    参数:
    ----------
    CIJ : NxN np.ndarray
        有向图的邻接矩阵,可以是二进制或带权重的。

    返回:
    -------
    J : ZxZ np.ndarray
        联合度分布矩阵
        (由于matlab的一维索引,矩阵被偏移了一个位置)
    J_od : int
        具有 od>id 的顶点数量
    J_id : int
        具有 id>od 的顶点数量
    J_bl : int
        具有 id==od 的顶点数量

    注意:
    -----
    权重信息将被忽略。
    '''
    # 确保CIJ矩阵是二进制的,如果CIJ不是二进制的,将进行转换
    CIJ = binarize(CIJ, copy=True)  
    
    # 计算节点的入度和出度
    n = len(CIJ)  # 节点总数
    id = np.sum(CIJ, axis=0)  # 入度 = CIJ矩阵的列和
    od = np.sum(CIJ, axis=1)  # 出度 = CIJ矩阵的行和

    # 创建联合度分布矩阵
    # 注意:矩阵偏移了一个位置,以适应id和od为零的情况
    # 矩阵的上三角部分有od>id的顶点
    # 矩阵的下三角部分有id>od的顶点
    # 对角线有id=od的顶点
    szJ = np.max((id, od)) + 1  # 联合度矩阵的大小
    J = np.zeros((szJ, szJ))  # 初始化联合度矩阵

    # 填充联合度矩阵
    for i in range(n):
        J[id[i], od[i]] += 1  # 对每个节点,增加其对应的id和od的计数

    # 计算不同区域的数量
    J_od = np.sum(np.triu(J, 1))  # 上三角部分(不包括对角线)的和,od>id的顶点数
    J_id = np.sum(np.tril(J, -1))  # 下三角部分(不包括对角线)的和,id>od的顶点数
    J_bl = np.sum(np.diag(J))  # 对角线的和,id==od的顶点数

    return J, J_od, J_id, J_bl

有向图联合度矩阵的计算实例

# 使用实例:
# 假设我们有一个3x3的有向图邻接矩阵,其中1表示存在边,0表示不存在边
CIJ_example = np.array([
    [0, 1, 0],  # 节点0有一个出边到节点1
    [0, 0, 1],  # 节点1有一个出边到节点2
    [1, 0, 0]   # 节点2有一个入边从节点0
])

# 调用jdegree函数计算联合度分布
J_matrix, J_od_count, J_id_count, J_bl_count = jdegree(CIJ_example)

# 打印结果
print("Joint degree distribution matrix:\n", J_matrix)
# array([[0., 0.],
#       [0., 3.]])
print("Number of vertices with outdegree > indegree:", J_od_count)	# 0.0
print("Number of vertices with indegree > outdegree:", J_id_count)	# 0.0
print("Number of vertices with indegree == outdegree:", J_bl_count)	# 3.0

有向图vs无向图的联合度矩阵计算

对于有向图来说,联合度矩阵的定义会稍微复杂一些,因为我们需要区分入度(in-degree)和出度(out-degree)。我们需要分别计算每个节点的入度和出度,然后构建一个联合度矩阵,表示入度和出度之间的关系。

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Brain Connectivity Toolbox(BCT)是一个用于功能和结构性脑连接性研究的 MATLAB 工具包。它提供了一系列函数和算法,用于处理和分析基于脑影像数据的神经网络。以下是关于如何使用BCT的简要说明。 首先,确保你的计算机上安装了MATLAB软件。然后,下载并安装BCT工具箱。你可以在其官方网站或其他可靠的科学研究网站上找到和下载。 安装完后,在MATLAB的命令窗口中输入 "brain connectivity toolbox" 或 "bct" 来启动工具包。你将会看到一个帮助页面,其中包含各种函数和用法的详细信息。 BCT提供了许多功能,可以用于构建、分析和可视化脑连接性网络。其中一些常用的功能包括: 1. 构建连接矩阵:使用BCT可以从功能或结构影像数据中创建连接矩阵。你可以使用不同的阈值方法、距离度量和阈值值来定义连接。 2. 网络分析:使用BCT可以计算网络的多种特征,包括度、聚类系数、特征路径长度、小世界性等。这些特征可以用来描述网络的整体和局部特性。 3. 功能网络分析:使用BCT,可以对功能网络进行动态分析,包括网络状态的变化和功能模块的发现。 4. 结构网络分析:BCT提供了一些功能来研究脑的结构网络,例如模块度检测、网络模型拟合和模块发现算法。 5. 可视化:借助BCT,你可以可视化脑网络和其特征,例如使用模块图来显示模块结构,绘制连接强度和权重等。 除了这些基本的功能外,BCT还提供了许多其他高级功能和算法,具体取决于你研究的需求。你可以通过查阅BCT文档和使用示例来深入了解和使用这些功能。 总之,Brain Connectivity Toolbox是一个强大的工具包,用于功能和结构性脑连接性的研究。通过使用BCT,你可以构建、分析和可视化脑网络,以增进对脑连接性的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值