如何画一个漂亮的功能连接矩阵图

绘制功能连接矩阵热力图教程
本文将介绍如何利用MATLAB程序绘制功能连接矩阵热力图,常见于神经科学领域的顶级期刊。程序简单易用,能生成清晰的脑网络矩阵图。详细步骤包括下载代码和示例数据,组织文件,以及在MATLAB中运行代码生成图片。

下面将介绍一种画功能连接矩阵热力图的程序。该程序使用简单,有了改代码再也不用担心类似下图的矩阵热力图。

以下几幅图都是来自一些神经、精神、心理学的顶级期刊,包括nature medicine,nature communications、brain等。这些图是以矩热力图的形式展示的功能连接或者统计学结果图。我们可以看到属于不同的网络的节点的连接被一些网格线分割开,很容易让别人识别脑网络。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

那么这种图是怎么做出来的呢?本期我们将给大家介绍一个专门用于做这种矩阵热力图的程序,并教大家如何使用改程序做出高清的用于直接投稿用的图片。

以下图片是使用笔者改程序做出来的矩阵热力图,这个图反映的是sub001的功能连接。

在这里插入图片描述

这个功能连接是一个114114的矩阵,表示有114个节点。另外我们有一个叫做netIndex.mat的文件,里面储存的是114个节点的网络标签,即每一个节点属于第几个网络。netIndex.mat是一个1114的向量,比如第1个位置的元素值表示第1个节点属于哪个脑网络。

进入具体操作正题:

  • 第1步,下载代码和例子数据:

代码下载地址(进入github项目后可以下载我的整个项目,也可以只下载该代码,最简单的方式就是直接把代码复制到matlab新建的函数里面):

可视化代码

The codes in this folder are used to visualization.

lc_circleplot is used to plot network in circle format.

lc_netplot is used to plot network in square format.

lc_plot_mean_tvalue is used to plot mean tvalues within or between networks.

数据下载地址(将其中的netIndex.mat和sub001.mat下载下来):

数据下载地址

  • 第2步,整理下载的文件:

将下载的两个.mat文件(netIndex.mat 和sub001.mat)放在一个叫做toy_data的文件夹下。并将下载的代码(lc_netplot.m)放在与toy_data同级的文件下。

  • 第3步,运行代码:

代码setpath到matlab路径后,在matlab命令窗口输入”lc_netplot”后,程序会在窗口打印出两个使用的例子,分别是EXAMPLE1和EXAMPLE 2.复制其中一个例子,到窗口,回车即可运行代码。运行结束后,图片会保存到toy_data文件夹下。

注:转载于公众号——脑之说。

function lc_netplot(varargin)
% LC_NETPLOT
% PURPOSE: plot functional connectivity network using grid format. 
% NOTO: This function will automatically sort network according to net_index.
% Parameters:
% -----------
%   REQUIRED:
%       [--net, -n]: path str | .mat matrix
%           Functional connectivity network that needs to be plotted.
%       [--net_index, -ni]: path str | .mat vector
%           network index, each node has a net_index indicating its network index
%   OPTIONAL:
%      [--if_add_mask, -iam]: int, 0 or 1
%           If add mask to net for filtering.
%      [--mask, -m]: path str | .mat matrix
%           Mask that used to filter the net.
%      [--how_disp, -hd]: str:: 'only_neg', 'only_pos' or 'all'
%           how display the network
%      [--if_binary, -ib]: int, 0 or 1
%           If binary the network.
%      [--which_group, -wg]: int
%           If the network .mat file has multiple 2D matrix, then choose which one to display.
%      [--linewidth, -lw]: float 
%           separation line width
%      [--linecolor, -lc]: color string 
%           separation line color
%      [--is_legend, -il]: int
%          If show legend.
%      [--legends, -lg]: cell
%          legends of each network.
%      [--legend_fontsize, -lgf]: float
%          fontsize of the legends
%   
% EXAMPLE:
% lc_netplot('-n', 'tvalue_medication.mat', '-ni', 'netIndex.mat')
% AUTHOR: Li Chao
% EMAIL: lichao19870617@gmail.com, lichao19870617@163.com
% If you used this code, please cite the code

if nargin == 0
    help lc_netplot
    return;
end

[net, if_add_mask, mask, how_disp, if_binary, which_group, net_index, linewidth, linecolor, is_legend, legends, legend_fontsize] = ...
            parseInputs(varargin{:});

% net
if isa(net, 'char')
    net=importdata(net);
else
    net=net;
end

% show postive and/or negative
if strcmp(how_disp,'only_pos')
    net(net<0)=0;
elseif strcmp(how_disp,'only_neg')
    net(net>0)=0;
elseif strcmp(how_disp,'all')
    disp('show both postive and negative')
else
    disp('Did not specify show positive or negative!')
    return
end

% when matrix is 3D, show which (the 3ith dimension)
if numel(size(net))==3
    %     net=squeeze(net(which_group,:,:));
    net=squeeze(net(:,:,which_group));
end

% transfer the weighted matrix to binary
if if_binary
    net(net<0)=-1;
    net(net>0)=1;
end

% mask
if if_add_mask
    if isa(mask, 'char')
        mask=importdata(mask);
    else
        mask=mask;
    end
    
    % when mask is 3D, show which (the 3ith dimension)
    if numel(size(mask))==3
        mask=squeeze(mask(which_group,:,:));
    end
    
    % extract data in mask
    net=net.*mask;
end

% sort the matrix according to network index
if ischar(net_index)
    net_index=importdata(net_index);
elseif ismatrix(net_index)
end
[index,re_net_index,re_net]=lc_ReorganizeNetForYeo17NetAtlas(net,net_index);

% plot: insert separate line between each network
lc_InsertSepLineToNet(re_net, re_net_index, linewidth, linecolor, is_legend, legends, legend_fontsize);
end


function [net, if_add_mask, mask, how_disp, if_binary, which_group, net_index, linewidth, linecolor, is_legend, legends, legend_fontsize] = ...
            parseInputs(varargin)
% Varargin parser

% Initialize
if_add_mask = 0;
mask = '';
how_disp='all';
if_binary=0;
which_group=1;
linewidth = 0.5;
linecolor = 'k';
is_legend = 0;
legends = '';
legend_fontsize = 10;

if( sum(or(strcmpi(varargin,'--net'),strcmpi(varargin,'-n')))==1)
    net = varargin{find(or(strcmpi(varargin,'--net'),strcmp(varargin,'-n')))+1};
else
    error('Please specify net!');
end

if( sum(or(strcmpi(varargin,'--if_add_mask'),strcmpi(varargin,'-iam')))==1)
    if_add_mask = varargin{find(or(strcmpi(varargin,'--if_add_mask'),strcmp(varargin,'-iam')))+1};
end

if( sum(or(strcmpi(varargin,'--mask'),strcmpi(varargin,'-m')))==1)
    mask = varargin{find(or(strcmpi(varargin,'--mask'),strcmp(varargin,'-m')))+1};
end

if( sum(or(strcmpi(varargin,'--how_disp'),strcmpi(varargin,'-hd')))==1)
    how_disp = varargin{find(or(strcmpi(varargin,'--how_disp'),strcmp(varargin,'-hd')))+1};
end

if( sum(or(strcmpi(varargin,'--if_binary'),strcmpi(varargin,'-ib')))==1)
    if_binary = varargin{find(or(strcmpi(varargin,'--if_binary'),strcmp(varargin,'-ib')))+1};
end

if( sum(or(strcmpi(varargin,'--which_group'),strcmpi(varargin,'-wg')))==1)
    which_group = varargin{find(or(strcmpi(varargin,'--which_group'),strcmp(varargin,'-wg')))+1};
end

if( sum(or(strcmpi(varargin,'--net_index'),strcmpi(varargin,'-ni')))==1)
    net_index = varargin{find(or(strcmpi(varargin,'--net_index'),strcmp(varargin,'-ni')))+1};
end

if( sum(or(strcmpi(varargin,'--linewidth'),strcmpi(varargin,'-lw')))==1)
    linewidth = varargin{find(or(strcmpi(varargin,'--linewidth'),strcmp(varargin,'-lw')))+1};
end

if( sum(or(strcmpi(varargin,'--linecolor'),strcmpi(varargin,'-lc')))==1)
    linecolor = varargin{find(or(strcmpi(varargin,'--linecolor'),strcmp(varargin,'-lc')))+1};
end

if( sum(or(strcmpi(varargin,'--is_legend'),strcmpi(varargin,'-il')))==1)
    is_legend = varargin{find(or(strcmpi(varargin,'--is_legend'),strcmp(varargin,'-il')))+1};
end

if( sum(or(strcmpi(varargin,'--legends'),strcmpi(varargin,'-lg')))==1)
   legends = varargin{find(or(strcmpi(varargin,'--legends'),strcmp(varargin,'-lg')))+1};
end

if( sum(or(strcmpi(varargin,'--legend_fontsize'),strcmpi(varargin,'-lgf')))==1)
   legend_fontsize = varargin{find(or(strcmpi(varargin,'--legend_fontsize'),strcmp(varargin,'-lgf')))+1};
end

end

function lc_InsertSepLineToNet(net, re_net_index, linewidth, linecolor, is_legend, legends, legend_fontsize)
% 此代码的功能:在一个网络矩阵种插入网络分割线,以及bar
% 此分割线将不同的脑网络分开
% 不同颜色的区域,代表一个不同的网络
% input
%   net:一个网络矩阵,N*N,N为节点个数,必须为对称矩阵
%   network_index: network index of each node.
%   location_of_sep:分割线的index,为一个向量,比如[3,9]表示网络分割线分别位于3和9后面
%% input
% if not given location_of_sep, then generate it using network_index;
uni_id = unique(re_net_index);
location_of_sep = [0; cell2mat(arrayfun( @(id) max(find(re_net_index == id)), uni_id, 'UniformOutput',false))];

if size(net,1)~=size(net,2)
    error('Not a symmetric matrix!\n');
end

%%

%% Gen new sep line and new network
n_node = length(net);
% New sep
num_sep = numel(location_of_sep);
location_of_sep_new = location_of_sep;
for i =  2 : num_sep
    location_of_sep_new(i:end) = location_of_sep_new(i:end) + 1;
end
% New network
net_insert_line = zeros(n_node + num_sep, n_node + num_sep);
for i = 1:num_sep-1
    % Rows iteration
    start_point =  location_of_sep_new(i) + 1;
    end_point = location_of_sep_new(i+1) - 1;
    start_point_old =  location_of_sep(i) + 1;
    end_point_old = location_of_sep(i+1);
    % Columns iteration
    for j = 1 : num_sep - 1
        start_point_j =  location_of_sep_new(j) + 1;
        end_point_j = location_of_sep_new(j+1) - 1;
        start_point_old_j =  location_of_sep(j) + 1;
        end_point_old_j = location_of_sep(j+1);
        net_insert_line(start_point : end_point, start_point_j : end_point_j) = ...
                    net(start_point_old : end_point_old, start_point_old_j : end_point_old_j);
    end
end
imagesc(net_insert_line); hold on;
x = repmat(location_of_sep_new', num_sep ,1);
y = repmat(location_of_sep_new,1, num_sep);
x(:,end) = x(:,end) + 1.5;
y(end,:) = y(end, :) + 1.5;
z = zeros(size(x));
mesh(x,y,z,...
    'EdgeColor',linecolor,...
    'FaceAlpha',0,...
    'LineWidth',linewidth);
view(2);
grid off
% lc_line(location_of_sep, n_node, linewidth, linecolor);
hold on;
% bar region
n_node_new = length(net_insert_line);
extend = n_node_new / 10;
xlim([0, n_node_new + extend]);
ylim([0, n_node_new + extend]);
lc_bar_region_of_each_network(location_of_sep_new, n_node_new, extend, is_legend, legends, legend_fontsize);
axis off
end

% function lc_line(location_of_sep, n_node, linewidth, linecolor)
% % nNode: node个数
% n_net = length(location_of_sep);
% for i=1:n_net
%     if (i == 1)  
%         % Y
%         line([location_of_sep(i), location_of_sep(i)],[0, n_node],'color',linecolor,'LineWidth',linewidth);
%         % X
%         line([0, n_node],[location_of_sep(i), location_of_sep(i)],'color',linecolor,'LineWidth',linewidth);
%     elseif (i == n_net)
%         % Y
%         line([location_of_sep(i) + 0.5, location_of_sep(i) + 0.5],[0, n_node],'color',linecolor,'LineWidth',linewidth);
%         % X
%         line([0, n_node],[location_of_sep(i) + 0.5, location_of_sep(i) + 0.5],'color',linecolor,'LineWidth',linewidth);
%         
%     else
%         % Y
%         line([location_of_sep(i) + 0.5, location_of_sep(i) + 0.5],[0, n_node],'color',linecolor,'LineWidth',linewidth);
%         % X
%         line([0, n_node],[location_of_sep(i) + 0.5, location_of_sep(i) + 0.5],'color',linecolor,'LineWidth',linewidth);
%     end
%     
% end
% end

function lc_bar_region_of_each_network(location_of_sep, n_node, extend, is_legend, legends, legend_fontsize)
% To plot bar with sevral regions, each region with a unique color
% representting a network.
n_net = length(location_of_sep);
randseed(1);
color = jet(n_net) / 1.2;
barwidth = abs((n_node + extend / 2) - (n_node+extend));
extend_of_legends = extend + 4 ;
h = zeros(n_net - 1, 1);
for i = 1 : n_net-1
    h(i) = fill([location_of_sep(i), location_of_sep(i+1), location_of_sep(i+1), location_of_sep(i)], [n_node + extend / 2, n_node + extend / 2, n_node+extend n_node + extend], color(i,:));
    fill([ n_node + barwidth, n_node + barwidth, n_node + extend, n_node + extend], [location_of_sep(i), location_of_sep(i+1), location_of_sep(i+1), location_of_sep(i)], color(i,:))
    if is_legend
        % Y axix
        text(n_node + extend_of_legends, (location_of_sep(i+1) - location_of_sep(i)) / 2 +  location_of_sep(i),...
            legends{i}, 'fontsize', legend_fontsize, 'rotation', 0);
         % X axix
        text((location_of_sep(i+1) - location_of_sep(i)) / 2 +  location_of_sep(i), n_node + extend_of_legends,...
            legends{i}, 'fontsize', legend_fontsize, 'rotation', -90);
    end
end
end
### 绘制4×4按键矩阵电路图的方法 在嘉立创EDA软件中绘制4×4按键矩阵电路图的过程涉及创建原理图和PCB布局。以下是关于如何实现这一目标的具体说明: #### 1. 创建原理图 在嘉立创EDA中,可以利用现有的元件库快速完成4×4按键矩阵的设计。 - 首先,在原理图编辑器中放置16个按键开关(SPST)。这些开关可以用作矩阵中的每个按键。 - 将按键按照行列方式进行连接。具体来说,将4条行线分别命名为`ROW0`, `ROW1`, `ROW2`, 和`ROW3`;同样地,定义4条列线分别为`COL0`, `COL1`, `COL2`, 和`COL3`[^1]。 - 每个按键的一端应连接到某一行线上,另一端则连接至某一列线。例如,第一个按键可连接于`ROW0`与`COL0`之间,第二个按键位于`ROW0`与`COL1`间等等。 ```plaintext | COL0 | COL1 | COL2 | COL3 | |------|------|------|------| | ROW0 | K1 | K2 | K3 | K4 | | ROW1 | K5 | K6 | K7 | K8 | | ROW2 | K9 | K10 | K11 | K12 | | ROW3 | K13 | K14 | K15 | K16 | ``` - 行线和列线最终应当接入单片机的I/O端口中用于扫描操作[^2]。 #### 2. 设置电阻网络 (推荐) 为了防止按键抖动以及提高稳定性,可以在每一条行线或者列线上串联一个上拉或下拉电阻(一般取值范围为1kΩ~10kΩ)[^2]。这种做法有助于确保即使没有按键被按下时也有稳定的逻辑电平输出给MCU处理。 #### 3. 转入PCB设计阶段 一旦完成了原理图之后就可以生成对应的网表文件并导入到PCB编辑界面当中去布置实际物理位置上的布线工作了: - 根据需要调整各个元器件的位置使其紧凑合理以便后续加工制造方便; - 对所有的信号走线进行合理的规划避免干扰现象发生. ### 示例代码片段展示部分功能实现思路 虽然题目主要关注的是硬件层面的内容而非编程方面的东西,但是提供一段简单的C语言伪代码可以帮助理解整个系统的运作机制. ```c #include <reg51.h> sbit ROW0=P2^0; sbit ROW1=P2^1; sbit ROW2=P2^2; sbit ROW3=P2^3; void main(){ while(1){ // Scan rows and read columns... } } ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值