MATLAB | 绘图复刻(十一) | 截断的含散点及误差棒的分组柱状图

news2025/2/14 2:52:59

hey大家好久不见,本期带来一篇绘图复刻,居然已经出到第11篇了,不知道有朝一日有没有机会破百,本期绘制的是《PNAS》期刊中pnas.2200057120文章的figure03,文章题目为Intranasal delivery of full-length anti-Nogo-A antibody: A potential alternative route for therapeutic antibodies to central nervous system targets可在以下网址下载该文章pdf原文:

  • https://www.pnas.org/doi/epdf/10.1073/pnas.2200057120

本期要复刻的绘图长这样:

本人复刻的效果长这样:

虽然还是有些许不同但是大部分元素已经还原出来了,以下为教程部分:

请尽量使用新版本的MATLAB,比较旧版本的MATLAB无XJitter功能,本人目前较忙近期不会有空开发类似功能,因此在我未有空开发相关功能前,请尽量使用比较新的版本!!!!!!!!~


教程部分

0 数据准备

这里随便随机生成了一点数据,文章中的五个颜色都被我提取了出来,我们这次先取用前两个颜色:

figure('Units','normalized','Position',[.2,.3,.36,.45],'Color','w');

rng(24)
% 随机生成了两组数据
DataA = rand(7,1)*ones(1,5).*2+rand(7,5)./3.5;
DataB = rand(7,1)*ones(1,5)./2+rand(7,5)./3.5;
meanData = [mean(DataA,2), mean(DataB,2)];

% 文章图片中的颜色数据
CList = [188,188,240; 160,161,166; 237,187,128;
         177,202,233; 245,185,192]./255;
CList = CList([1,2],:);
% CList = CList([4,5],:);

% 横坐标标签文本
NameList = {'Cortex';
            'Hippocampus';
            'Cerebellum';
            'Brainstem';
            'Cervical spinal cord';
            'Thoracic spinal cord';
            'Lumbar spinal cord'};

1 基础绘图

柱状图

hold on
% 绘制柱状图 ---------------------------------------------------------------
barHdl = bar(meanData,'EdgeColor','none','FaceAlpha',.5,'BarWidth',.7);
% 修改配色
barHdl(1).FaceColor = CList(1,:);
barHdl(2).FaceColor = CList(2,:);

散点图

% 绘制散点图 ---------------------------------------------------------------
XA = barHdl(1).XEndPoints.'*ones(1,size(DataA,2));
scatter(XA(:),DataA(:),55,'filled','o','MarkerEdgeColor','k','LineWidth',.8,...
                      'CData',CList(1,:),'XJitter','rand','XJitterWidth',0.15)
XB = barHdl(2).XEndPoints.'*ones(1,size(DataB,2));
scatter(XB(:),DataB(:),55,'filled','o','MarkerEdgeColor','k','LineWidth',.8,...
                      'CData',CList(2,:),'XJitter','rand','XJitterWidth',0.15)

误差棒

这里直接用的标准差:

% 绘制误差棒 ---------------------------------------------------------------
errorbar(barHdl(1).XEndPoints,meanData(:,1),std(DataA,0,2),'vertical',...
    'LineStyle','none','LineWidth',1,'Color','k')
errorbar(barHdl(2).XEndPoints,meanData(:,2),std(DataB,0,2),'vertical',...
    'LineStyle','none','LineWidth',1,'Color','k')


3 坐标区域简单修饰

主要是调整字体,并修改X轴刻度标签:

% 绘制误差棒 ---------------------------------------------------------------
errorbar(barHdl(1).XEndPoints,meanData(:,1),std(DataA,0,2),'vertical',...
    'LineStyle','none','LineWidth',1,'Color','k')
errorbar(barHdl(2).XEndPoints,meanData(:,2),std(DataB,0,2),'vertical',...
    'LineStyle','none','LineWidth',1,'Color','k')


4 截断坐标轴

这里用的我之前写的一个函数,为了怕大家找起来麻烦,放在了文末及文末的gitee仓库里。

以下是调用文末截断坐标轴函数实现的:

% 截断坐标轴
truncAxis('y',[1,1.4]);


5 坐标轴精修

包括隐藏baseline,添加Y轴标签,修改坐标轴粗细及刻度方向等:

fig = gcf;
ax1 = fig.Children(1);
ax2 = fig.Children(2);

% 隐藏基线
ax1.XColor = 'none';
ax1.Children(end).BaseLine.Color = 'none';

% 坐标轴修饰
ax1.LineWidth = 1.5; 
ax2.LineWidth = 1.5;
ax1.TickDir = 'out';
ax2.TickDir = 'out';

% 增添Y轴标签
ax1.YLabel.String = 'ug of Ab/ g wet weight of tissue';
ax1.YLabel.Position = [0 1.4 -1];
ax1.YLabel.FontSize = 15;


6 添加显著性标注

就一个柱子一个柱子加吧,改改序号和字符就能得到比较符合想法的效果:

% 随便加点显著性标志

N = 2; % 第二个柱
S = '***';
% 要修改右侧柱请改成barHdl(2)及DataB(N,:)
X = barHdl(1).XEndPoints(N);
Y = max(DataA(N,:))+.1;
errorbar(X,Y,.2,'horizontal','LineStyle','none','LineWidth',1,'Color','k')
text(X,Y,S,'FontSize',15,'FontWeight','bold','FontName','Arial',...
    'HorizontalAlignment','center','VerticalAlignment','baseline')

N = 3; % 第三个柱
S = '****';
% 要修改右侧柱请改成barHdl(2)及DataB(N,:)
X = barHdl(1).XEndPoints(N);
Y = max(DataA(N,:))+.1;
errorbar(X,Y,.2,'horizontal','LineStyle','none','LineWidth',1,'Color','k')
text(X,Y,S,'FontSize',15,'FontWeight','bold','FontName','Arial',...
    'HorizontalAlignment','center','VerticalAlignment','baseline')


N = 6; % 第六个柱
S = '****';
% 要修改右侧柱请改成barHdl(2)及DataB(N,:)
X = barHdl(1).XEndPoints(N);
Y = max(DataA(N,:))+.1;
errorbar(X,Y,.2,'horizontal','LineStyle','none','LineWidth',1,'Color','k')
text(X,Y,S,'FontSize',15,'FontWeight','bold','FontName','Arial',...
    'HorizontalAlignment','center','VerticalAlignment','baseline')


更多颜色展示


完整代码

教程完整代码

% code for pnas.2200057120fig03
% by slandarer
% bar chart with trunc-axis

figure('Units','normalized','Position',[.2,.3,.36,.45],'Color','w');

rng(24)
% 随机生成了两组数据
DataA = rand(7,1)*ones(1,5).*2+rand(7,5)./3.5;
DataB = rand(7,1)*ones(1,5)./2+rand(7,5)./3.5;
meanData = [mean(DataA,2), mean(DataB,2)];

% 文章图片中的颜色数据
CList = [188,188,240; 160,161,166; 237,187,128;
         177,202,233; 245,185,192]./255;
CList = CList([1,2],:);
% CList = CList([4,5],:);

% 横坐标标签文本
NameList = {'Cortex';
            'Hippocampus';
            'Cerebellum';
            'Brainstem';
            'Cervical spinal cord';
            'Thoracic spinal cord';
            'Lumbar spinal cord'};

hold on
% 绘制柱状图 ---------------------------------------------------------------
barHdl = bar(meanData,'EdgeColor','none','FaceAlpha',.5,'BarWidth',.7);
% 修改配色
barHdl(1).FaceColor = CList(1,:);
barHdl(2).FaceColor = CList(2,:);
% 绘制散点图 ---------------------------------------------------------------
XA = barHdl(1).XEndPoints.'*ones(1,size(DataA,2));
scatter(XA(:),DataA(:),55,'filled','o','MarkerEdgeColor','k','LineWidth',.8,...
                      'CData',CList(1,:),'XJitter','rand','XJitterWidth',0.15)
XB = barHdl(2).XEndPoints.'*ones(1,size(DataB,2));
scatter(XB(:),DataB(:),55,'filled','o','MarkerEdgeColor','k','LineWidth',.8,...
                      'CData',CList(2,:),'XJitter','rand','XJitterWidth',0.15)
% 绘制误差棒 ---------------------------------------------------------------
errorbar(barHdl(1).XEndPoints,meanData(:,1),std(DataA,0,2),'vertical',...
    'LineStyle','none','LineWidth',1,'Color','k')
errorbar(barHdl(2).XEndPoints,meanData(:,2),std(DataB,0,2),'vertical',...
    'LineStyle','none','LineWidth',1,'Color','k')

% 坐标区域简单修饰
ax = gca;
ax.XTick = 1:length(barHdl(1).XEndPoints);
ax.XTickLabel = NameList(:);
ax.FontName = 'Arial';
ax.FontWeight = 'bold';
ax.FontSize = 11;
ax.XTickLabelRotation = 35;

% 截断坐标轴
truncAxis('y',[1,1.4]);
fig = gcf;
ax1 = fig.Children(1);
ax2 = fig.Children(2);

% 隐藏基线
ax1.XColor = 'none';
ax1.Children(end).BaseLine.Color = 'none';

% 坐标轴修饰
ax1.LineWidth = 1.5; 
ax2.LineWidth = 1.5;
ax1.TickDir = 'out';
ax2.TickDir = 'out';

% 增添Y轴标签
ax1.YLabel.String = 'ug of Ab/ g wet weight of tissue';
ax1.YLabel.Position = [0 1.4 -1];
ax1.YLabel.FontSize = 15;

% -------------------------------------------------------------------------
% 随便加点显著性标志

N = 2; % 第二个柱
S = '***';
% 要修改右侧柱请改成barHdl(2)及DataB(N,:)
X = barHdl(1).XEndPoints(N);
Y = max(DataA(N,:))+.1;
errorbar(X,Y,.2,'horizontal','LineStyle','none','LineWidth',1,'Color','k')
text(X,Y,S,'FontSize',15,'FontWeight','bold','FontName','Arial',...
    'HorizontalAlignment','center','VerticalAlignment','baseline')

N = 3; % 第三个柱
S = '****';
% 要修改右侧柱请改成barHdl(2)及DataB(N,:)
X = barHdl(1).XEndPoints(N);
Y = max(DataA(N,:))+.1;
errorbar(X,Y,.2,'horizontal','LineStyle','none','LineWidth',1,'Color','k')
text(X,Y,S,'FontSize',15,'FontWeight','bold','FontName','Arial',...
    'HorizontalAlignment','center','VerticalAlignment','baseline')


N = 6; % 第六个柱
S = '****';
% 要修改右侧柱请改成barHdl(2)及DataB(N,:)
X = barHdl(1).XEndPoints(N);
Y = max(DataA(N,:))+.1;
errorbar(X,Y,.2,'horizontal','LineStyle','none','LineWidth',1,'Color','k')
text(X,Y,S,'FontSize',15,'FontWeight','bold','FontName','Arial',...
    'HorizontalAlignment','center','VerticalAlignment','baseline')

截断坐标轴工具函数完整代码

function truncAxis(varargin)
% @author : slandarer
% gzh  : slandarer随笔

% 获取参数
if isa(varargin{1},'matlab.graphics.axis.Axes')
    ax=varargin{1};varargin(1)=[];
else
    ax=gca;
end
hold(ax,'on');
% box(ax,'off')
ax.XAxisLocation='bottom';
ax.YAxisLocation='left';
axisPos=ax.Position;
axisXLim=ax.XLim;
axisYLim=ax.YLim;
axisXScale=diff(axisXLim);
axisYScale=diff(axisYLim);
truncRatio=1/20;
Xtrunc=[];Ytrunc=[];
for i=1:length(varargin)-1
    switch true
        case strcmpi('X',varargin{i}),Xtrunc=varargin{i+1};
        case strcmpi('Y',varargin{i}),Ytrunc=varargin{i+1};
    end
end
switch true
    case isempty(Xtrunc)
        % 复制坐标区域
        ax2=copyAxes(ax);
        % 修改轴基础属性
        ax2.XTickLabels=[];
        ax2.XColor='none';
        % 修改坐标区域范围
        ax.YLim=[axisYLim(1),Ytrunc(1)];
        ax2.YLim=[Ytrunc(2),axisYLim(2)];
        % 坐标区域重定位
        ax.Position(4)=axisPos(4)*(1-truncRatio)/(axisYScale-diff(Ytrunc))*(Ytrunc(1)-axisYLim(1));
        ax2.Position(2)=axisPos(2)+ax.Position(4)+axisPos(4)*truncRatio;
        ax2.Position(4)=axisPos(4)*(1-truncRatio)/(axisYScale-diff(Ytrunc))*(axisYLim(2)-Ytrunc(2));
        % 链接轴范围变动
        linkaxes([ax,ax2],'x')
        % 添加线和标识符
        if strcmp(ax.Box,'on')
        ax.Box='off';ax2.Box='off';
        annotation('line',[1,1].*(ax.Position(1)+ax.Position(3)),[ax.Position(2),ax.Position(2)+ax.Position(4)],'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax.Position(1)+ax.Position(3)),[ax2.Position(2),ax2.Position(2)+ax2.Position(4)],'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax.Position(1),ax.Position(1)+ax.Position(3)],[1,1].*(ax2.Position(2)+ax2.Position(4)),'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        else
        annotation('line',[ax.Position(1),ax.Position(1)+ax.Position(3)],[1,1].*(ax.Position(2)+ax.Position(4)),'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax.Position(1),ax.Position(1)+ax.Position(3)],[1,1].*(ax2.Position(2)),'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        end
        createSlash([ax.Position(1)-.2,ax.Position(2)+ax.Position(4)-.2,.4,.4])
        createSlash([ax.Position(1)-.2,ax2.Position(2)-.2,.4,.4])
        createSlash([ax.Position(1)+ax.Position(3)-.2,ax.Position(2)+ax.Position(4)-.2,.4,.4])
        createSlash([ax.Position(1)+ax.Position(3)-.2,ax2.Position(2)-.2,.4,.4])
    case isempty(Ytrunc) 
        % 复制坐标区域
        ax2=copyAxes(ax);
        % 修改轴基础属性
        ax2.YTickLabels=[];
        ax2.YColor='none';
        % 修改坐标区域范围
        ax.XLim=[axisXLim(1),Xtrunc(1)];
        ax2.XLim=[Xtrunc(2),axisXLim(2)];
        % 坐标区域重定位
        ax.Position(3)=axisPos(3)*(1-truncRatio)/(axisXScale-diff(Xtrunc))*(Xtrunc(1)-axisXLim(1));
        ax2.Position(1)=axisPos(1)+ax.Position(3)+axisPos(3)*truncRatio;
        ax2.Position(3)=axisPos(3)*(1-truncRatio)/(axisXScale-diff(Xtrunc))*(axisXLim(2)-Xtrunc(2));
        % 链接轴范围变动
        linkaxes([ax,ax2],'y')
        % 添加线和标识符
        if strcmp(ax.Box,'on')
        ax.Box='off';ax2.Box='off';
        annotation('line',[ax.Position(1),ax.Position(1)+ax.Position(3)],[1,1].*(ax.Position(2)+ax.Position(4)),'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax2.Position(1),ax2.Position(1)+ax2.Position(3)],[1,1].*(ax.Position(2)+ax.Position(4)),'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax2.Position(1)+ax2.Position(3)),[ax2.Position(2),ax2.Position(2)+ax2.Position(4)],'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        else
        annotation('line',[1,1].*(ax.Position(1)+ax.Position(3)),[ax2.Position(2),ax2.Position(2)+ax2.Position(4)],'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax2.Position(1)),[ax2.Position(2),ax2.Position(2)+ax2.Position(4)],'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        end
        createSlash([ax.Position(1)+ax.Position(3)-.2,ax.Position(2)-.2,.4,.4])
        createSlash([ax2.Position(1)-.2,ax.Position(2)-.2,.4,.4])
        createSlash([ax.Position(1)+ax.Position(3)-.2,ax.Position(2)+ax.Position(4)-.2,.4,.4])
        createSlash([ax2.Position(1)-.2,ax.Position(2)+ax.Position(4)-.2,.4,.4])
    case (~isempty(Ytrunc))&(~isempty(Ytrunc))
        % 复制坐标区域
        ax2=copyAxes(ax);
        ax3=copyAxes(ax);
        ax4=copyAxes(ax);
        % 修改轴基础属性
        ax2.XTickLabels=[];
        ax2.XColor='none';
        ax3.XTickLabels=[];
        ax3.XColor='none';
        ax3.YTickLabels=[];
        ax3.YColor='none';
        ax4.YTickLabels=[];
        ax4.YColor='none';
        % 修改坐标区域范围
        ax.YLim=[axisYLim(1),Ytrunc(1)];
        ax.XLim=[axisXLim(1),Xtrunc(1)];
        ax2.XLim=[axisXLim(1),Xtrunc(1)];
        ax2.YLim=[Ytrunc(2),axisYLim(2)];
        ax3.XLim=[Xtrunc(2),axisXLim(2)];
        ax3.YLim=[Ytrunc(2),axisYLim(2)];
        ax4.XLim=[Xtrunc(2),axisXLim(2)];
        ax4.YLim=[axisYLim(1),Ytrunc(1)];
        % 坐标区域重定位
        ax.Position(3)=axisPos(3)*(1-truncRatio)/(axisXScale-diff(Xtrunc))*(Xtrunc(1)-axisXLim(1));
        ax.Position(4)=axisPos(4)*(1-truncRatio)/(axisYScale-diff(Ytrunc))*(Ytrunc(1)-axisYLim(1));
        ax2.Position(2)=axisPos(2)+ax.Position(4)+axisPos(4)*truncRatio;
        ax2.Position(3)=axisPos(3)*(1-truncRatio)/(axisXScale-diff(Xtrunc))*(Xtrunc(1)-axisXLim(1));
        ax2.Position(4)=axisPos(4)*(1-truncRatio)/(axisYScale-diff(Ytrunc))*(axisYLim(2)-Ytrunc(2));
        ax3.Position(1)=axisPos(1)+ax.Position(3)+axisPos(3)*truncRatio;
        ax3.Position(2)=axisPos(2)+ax.Position(4)+axisPos(4)*truncRatio;
        ax3.Position(3)=axisPos(3)*(1-truncRatio)/(axisXScale-diff(Xtrunc))*(axisXLim(2)-Xtrunc(2));
        ax3.Position(4)=axisPos(4)*(1-truncRatio)/(axisYScale-diff(Ytrunc))*(axisYLim(2)-Ytrunc(2));
        ax4.Position(1)=axisPos(1)+ax.Position(3)+axisPos(3)*truncRatio;
        ax4.Position(3)=axisPos(3)*(1-truncRatio)/(axisXScale-diff(Xtrunc))*(axisXLim(2)-Xtrunc(2));
        ax4.Position(4)=axisPos(4)*(1-truncRatio)/(axisYScale-diff(Ytrunc))*(Ytrunc(1)-axisYLim(1));
        % 链接轴范围变动
        linkaxes([ax3,ax2],'y')
        linkaxes([ax4,ax3],'x')
        linkaxes([ax,ax2],'x')
        linkaxes([ax,ax4],'y')
        % 添加线和标识符
        if strcmp(ax.Box,'on')
        ax.Box='off';ax2.Box='off';ax3.Box='off';ax4.Box='off';
        annotation('line',[ax.Position(1),ax.Position(1)+ax.Position(3)],[1,1].*(ax2.Position(2)+ax2.Position(4)),'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax3.Position(1),ax3.Position(1)+ax3.Position(3)],[1,1].*(ax2.Position(2)+ax2.Position(4)),'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax4.Position(1)+ax4.Position(3)),[ax3.Position(2),ax3.Position(2)+ax3.Position(4)],'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax4.Position(1)+ax4.Position(3)),[ax4.Position(2),ax4.Position(2)+ax4.Position(4)],'LineStyle','-','LineWidth',ax.LineWidth,'Color',ax.XColor);
        else
        annotation('line',[1,1].*(ax.Position(1)+ax.Position(3)),[ax2.Position(2),ax2.Position(2)+ax2.Position(4)],'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax3.Position(1)),[ax2.Position(2),ax2.Position(2)+ax2.Position(4)],'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax.Position(1)+ax.Position(3)),[ax.Position(2),ax.Position(2)+ax.Position(4)],'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[1,1].*(ax3.Position(1)),[ax.Position(2),ax.Position(2)+ax.Position(4)],'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax.Position(1),ax.Position(1)+ax.Position(3)],[1,1].*(ax.Position(2)+ax.Position(4)),'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax.Position(1),ax.Position(1)+ax.Position(3)],[1,1].*(ax2.Position(2)),'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax4.Position(1),ax4.Position(1)+ax4.Position(3)],[1,1].*(ax.Position(2)+ax.Position(4)),'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        annotation('line',[ax4.Position(1),ax4.Position(1)+ax4.Position(3)],[1,1].*(ax2.Position(2)),'LineStyle',':','LineWidth',ax.LineWidth,'Color',ax.XColor);
        end
        createSlash([ax.Position(1)-.2,ax.Position(2)+ax.Position(4)-.2,.4,.4])
        createSlash([ax.Position(1)-.2,ax2.Position(2)-.2,.4,.4])
        createSlash([ax4.Position(1)+ax4.Position(3)-.2,ax.Position(2)+ax.Position(4)-.2,.4,.4])
        createSlash([ax4.Position(1)+ax4.Position(3)-.2,ax2.Position(2)-.2,.4,.4])
        createSlash([ax.Position(1)+ax.Position(3)-.2,ax.Position(2)-.2,.4,.4])
        createSlash([ax.Position(1)+ax.Position(3)-.2,ax2.Position(2)+ax2.Position(4)-.2,.4,.4])
        createSlash([ax4.Position(1)-.2,ax.Position(2)-.2,.4,.4])
        createSlash([ax4.Position(1)-.2,ax2.Position(2)+ax2.Position(4)-.2,.4,.4])
        % 修改当前坐标区域,方便legend添加
        set(gcf,'currentAxes',ax3)
end
% 复制原坐标区域全部可复制属性
    function newAX=copyAxes(ax)
        axStruct=get(ax);
        fNames=fieldnames(axStruct);
        newAX=axes('Parent',ax.Parent);

        coeList={'CurrentPoint','XAxis','YAxis','ZAxis','BeingDeleted',...
            'TightInset','NextSeriesIndex','Children','Type','Legend'};
        for n=1:length(coeList)
            coePos=strcmp(fNames,coeList{n});
            fNames(coePos)=[];
        end
        
        for n=1:length(fNames)
            newAX.(fNames{n})=ax.(fNames{n});
        end

        copyobj(ax.Children,newAX)
    end
% 添加截断标识符函数
    function createSlash(pos)
        anno=annotation('textbox');
        anno.String='/';
        anno.LineStyle='none';
        anno.FontSize=15;
        anno.Position=pos;
        anno.FitBoxToText='on';
        anno.VerticalAlignment='middle';
        anno.HorizontalAlignment='center';
    end
end

以上已经是本文全部内容,若懒得复制代码,可以去以下gitee仓库获取全部代码:

https://gitee.com/slandarer/PLTreprint/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/863804.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SaaS BI数据可视化工具:免下载安装,登录即分析

之前有人问我,说:“BI数据可视化工具总是要下载安装,过程繁琐,没点IT基础的人也不太搞得定,有没有不用下载安装就能用的数据可视化工具?”答案当然是有的,那就是SaaS BI数据可视化工具。 SaaS …

并发——AQS原理以及AQS同步组件总结

文章目录 1 AQS 简单介绍2 AQS 原理2.1 AQS 原理概览2.2 AQS 对资源的共享方式2.3 AQS 底层使用了模板方法模式 3 Semaphore(信号量)-允许多个线程同时访问4 CountDownLatch (倒计时器)4.1 CountDownLatch 的两种典型用法4.2 CountDownLatch 的使用示例4…

生信豆芽菜-箱线图使用说明

网站:http://www.sxdyc.com/visualsBoxplot 一、使用方法 1.打开网址(http://www.sxdyc.com/singleCollectionTool?href-diff),选择“箱线图”。 准备数据: 第一个文件为特征的表达文件,第一列为样本&am…

机器人CPP编程基础-05完结The End

非常不可思议……之前四篇博文竟然有超过100的阅读量…… 此文此部分终结,没有继续写下去的必要了。 插入一个分享: 编程基础不重要了,只要明确需求,借助AI工具就能完成一个项目。 当然也不是一次成功,工具使用也需要…

PP模块生产过程检验(工序检验)

质量检验是在一些情形下对物料进行检查的一个操作,用于检验物料是否符合标准。 1.常见检验类型: (1)进货检验(Incoming material Quality Check,IQC) (2) 生产过程检验(In Process Quality Check,IQPC) (3) 最终检验/产品检验(Final Quality Check,FQC) (4)出…

【产品应用】一体化步进伺服电机在自动液体处理工作站中的应用

随着工业自动化的快速发展,自动液体处理工作站在医药、食品、化工等领域中发挥着越来越重要的作用。一体化步进伺服电机作为一种高集成的驱动元件,具有高精度、高速度和高稳定性的特点,被广泛应用于自动液体处理工作站中。本文将详细介绍一体…

同源建模-build loop

对于有残基缺失的晶体结构往往采用同源建模的方式补全,但常规的同源建模方法往往造成非缺失区域残基的挪动,有时我们并不想出现这种状况,尤其是涉及到多个截短体拼合的情况,这时就需要用到约束性同源建模的方法,只对缺…

对一线大厂游戏测试员的访谈实录,带你了解游戏测试

今天采访了一个在游戏行业做测试的同学,他所在的游戏公司是做大型多人在线角色扮演类的游戏,类似传奇游戏。他所在的公司目前有1200多人,是上市公司,目前游戏产品在国内海外都有市场。 因为我是一个对游戏无感的人,所…

户外组网摆脱布线困扰,工业5G网关实现无人值守、远程实时监控

在物联网通信技术发达的2023,网络覆盖对所及之处的全面覆盖,科技发展的促使下很多高危户外场景也在思考如何利用无线技术提高人员安全及现场无人化管理。 煤矿是我们国家不可缺少的重要能源,其开采过程的危险系数也是众所皆知的,…

CANdelaStudio 使用介绍

CANdela Studio使用_哔哩哔哩_bilibili 一.CANdelaStudio使用tips 1.开始菜单打开软件,避免软件字体是德文的 2.打开软件之后,用“Open”打开.cdd或者.cddt文件,不要双击文件打开,这样容易报错 3.查看软件版本信息 4.只有Admin版…

CKA认证真题(3)-- 绝对干货!

目录 前言 15. sidecar边车容器 16. 升级集群 17.备份还原etcd 前言 17道真题难度等级 一级 rbac cpu 扩容 pod指定节点 pv pod日志 排障 查看可用节点 多容器pod 节点维护 二级 networkpolicy service ingress pvc 三级 sidecar 升级集群 备份还原etcd 本系列有三篇博客…

kettle simple-jndi 配置中心

jdbc.properties配置 SampleData/typejavax.sql.DataSource SampleData/driverorg.h2.Driver SampleData/urljdbc:h2:file:./samples/db/sampledb;IFEXISTSTRUE SampleData/userPENTAHO_USER SampleData/passwordPASSWORD SampleDataAdmin/typejavax.sql.DataSource SampleDat…

用于共享大文件的4种大文件传输工具和软件

个人或团队工作时,大文件传输软件和网站能够提升工作效率、有效地管理工作内容。由于疫情的影响,有时我们需要在家办公,在这种情况下,能够分享文件的工具就显得格外重要。 每个公司都需要一个文件传输软件,让员工可以…

Java 成功实现通过网址URL截图保存

Java 实现通过网址URL截图 1.DjNativeSwing方式 (不好用)2.phantomjs方式 (截图还是有瑕疵)3.selenium方式 (满意,成功实现)maven 引入下载相关浏览器chrome下载相关浏览器chromedriver驱动后端…

一文搞懂STP(从原理到配置)

一、STP出现的背景 1. 单点故障 如图9-1所示,PC1和PC2通过LSW1相互通信,如果LSW1出现了故障,那么PC1和PC2将不能相互通信,这种现象我们称之为单点故障。为了解决这个问题,我们提出了冗余的拓扑结构。 图9-1单点故障 …

【数据结构】单链表OJ题(一)

🔥博客主页:小王又困了 📚系列专栏:数据结构 🌟人之为学,不日近则日退 ❤️感谢大家点赞👍收藏⭐评论✍️ 目录 一、移除链表元素 💡方法一: 💡方法二…

安卓如何快速定位native内存泄露。

步骤1)cat /proc/pid/status,观察下面俩个指标 RssAnon: 5300 kB //一直增大说明匿名映射的内存增大,malloc本质就是调用匿名映射分 配内存 RssFile: 26884 kB //文件句柄泄露&#…

JMeter 的并发设置教程

JMeter 是一个功能强大的性能测试工具,可以模拟许多用户同时访问应用程序的情况。在使用 JMeter 进行性能测试时,设置并发是非常重要的。本文将介绍如何在 JMeter 中设置并发和查看报告。 设置并发 并发是在线程组下的线程属性中设置的。 线程数&#…

谈一谈在两个商业项目中使用MVI架构后的感悟

作者:leobertlan 前言 当时项目采用MVP分层设计,组员的代码风格差异也较大,代码中类职责赋予与封装风格各成一套,随着业务急速膨胀,代码越发混乱。试图用 MVI架构 单向流 形成 掣肘 带来一致风格。 但这种做法不够以…

一文带你快速掌握如何在Windows系统和Linux系统中安装部署MongoDB

文章目录 前言一、 Windows系统中的安装启动1. 下载安装包2. 解压安装启动3. Shell连接(mongo命令)4. Compass-图形化界面客户端 二、 Linux系统中的安装启动和连接1. 下载安装包2. 解压安装3. 新建并修改配置文件4. 启动MongoDB服务5. 关闭MongoDB服务 总结 前言 为了巩固所学…