Note
Click here to download the full example code
Help function definition
Python code
import numpy as np
import time
import linecache
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib import patches
import matplotlib.ticker as ticker
from matplotlib.ticker import MultipleLocator
from matplotlib.collections import LineCollection
from matplotlib.colors import ListedColormap, BoundaryNorm
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
mpl.rcParams['font.family'] = 'Arial' #default font family
mpl.rcParams['mathtext.fontset'] = 'cm' #font for math
import os
from matplotlib.patches import Patch
from matplotlib.lines import Line2D
from matplotlib.patches import Rectangle
import copy
from matplotlib.path import Path
from matplotlib.textpath import TextPath
from matplotlib.font_manager import FontProperties
from matplotlib.transforms import Affine2D
from mpl_toolkits.mplot3d import Axes3D, art3d
from matplotlib.patches import PathPatch
def text3d(ax, xyz, s, zdir="z", size=0.1, angle=0,font='Arial',weight='normal',ha='left',va='center', **kwargs):
x, y, z = xyz
xlim,ylim,zlim=ax.get_xlim(),ax.get_ylim(),ax.get_zlim()
xmin,xmax,ymin,ymax,zmin,zmax=xlim[0],xlim[1],ylim[0],ylim[1],zlim[0],zlim[1]
xlen,ylen,zlen=xmax-xmin, ymax-ymin, zmax-zmin
minLen_axis=np.min([xlen,ylen,zlen])
aspect=ax.get_box_aspect()
fontscale=1
if zdir == "y": xy, z, fontscale = (x,z), y, (xlen/zlen)/(aspect[0]/aspect[2])
elif zdir == "x": xy, z, fontscale = (y,z), x, (ylen/zlen)/(aspect[1]/aspect[2])
else: xy, z, fontscale = (x,y), z, (xlen/ylen)/(aspect[0]/aspect[1])
path = TextPath((0, 0), s, size=size, prop = FontProperties(family=font,weight=weight))
V = copy.deepcopy(path.vertices)
if(ha=='center'):
V[:,0] -= (V[:,0].max() - V[:,0].min())/2 #
elif(ha=='right'):
V[:,0] -= V[:,0].max()
if(va=='center'):
V[:,1] -= (V[:,1].max() - V[:,1].min())/2 # 居中
elif(va=='top'):
V[:,1] -= V[:,1].max()
trans = Affine2D().rotate(angle/180*np.pi).scale(1,1/fontscale).translate(xy[0], xy[1])
# path = PathPatch(trans.transform_path(path), clip_on=False, **kwargs)
path = PathPatch(trans.transform_path(Path(V, path._codes)), clip_on=False, **kwargs)
ax.add_patch(path)
art3d.pathpatch_2d_to_3d(path, z=z, zdir=zdir)
def niceAxis_3D(ax, lw_major=0.5,lw_minor=0.25,color_major="0.50",color_minor="0.75",
alpha_pane=0.2,fill_pane=True,ec_pane='None',label3D=True,fs_label=0.1,
length_major=0.05,length_minor=0.02,offset_axislabel=3,frame_on=True,scaled=True):
# 坐标轴自定义
xlim,ylim,zlim=ax.get_xlim(),ax.get_ylim(),ax.get_zlim()
xmin,xmax,ymin,ymax,zmin,zmax=xlim[0],xlim[1],ylim[0],ylim[1],zlim[0],zlim[1]
# 1. 根据坐标轴范围设置坐标轴比例:假设xyz三轴以自然比例显示
xlen,ylen,zlen=xmax-xmin, ymax-ymin, zmax-zmin
minLen_axis=np.min([xlen,ylen,zlen])
xratio,yratio,zratio=[xlen,ylen,zlen]/minLen_axis
if(scaled):
ax.set_box_aspect((4*xratio,4*yratio,3*zratio)) # 默认比例是4:4:3
# 3. 重新定义网格线:注意mpl的三维绘图目前不支持grid()函数分别定义主刻度网格和副刻度网格属性
ax.grid(False) # 首先关闭默认网格
zorder_grid=-50
try:
ax.get_figure().draw_without_rendering() # new in 3.5: https://matplotlib.org/stable/users/prev_whats_new/whats_new_3.5.0.html#figure-now-has-draw-without-rendering-method
except:
try:
ax.get_figure().canvas.draw() # Old version
except:
pass
if(ax.get_xticklabels()[0]._text==''): return
# 主刻度线
linewidth, color, length = lw_major, color_major, length_major
if(type(length_major)==type([1,1,1])):
length=length_major[0]
# x轴
tickmin,tickmax,tickaxis,axislim=xmin,xmax,ax.xaxis,ax.get_xlim()
tickpos1,tickpos2=[ymin,ymax,ymax],[zmin,zmin,zmax]
for tick,label in zip(ax.get_xticks(),ax.get_xticklabels()):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot([tick,tick,tick],tickpos1,tickpos2, lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
text3d(ax, (tick, ymin-length*1.2*ylen, zmin), label.get_text(),size=fs_label*minLen_axis, fc=label.get_color(), ec="None", ha='center',va='top')
label.set_alpha(0)
ax.plot([tick,tick],[ymin,ymin-length*ylen],[zmin,zmin],lw=linewidth,color=label.get_color())
if(label3D):
ax.plot([xmin,xmax],[ymin,ymin],[zmin,zmin],lw=linewidth,color=label.get_color())
text3d(ax, ((xmin+xmax)/2, ymin-length*offset_axislabel*ylen, zmin), ax.get_xlabel(),
size=fs_label*minLen_axis, fc=label.get_color(), ec="None",ha='center',va='top')
# y轴
tickmin,tickmax,tickaxis,axislim=ymin,ymax,ax.yaxis,ax.get_ylim()
tickpos1,tickpos2=[xmax,xmax,xmin],[zmax,zmin,zmin]
if(type(length_major)==type([1,1,1])):
length=length_major[1]
for tick,label in zip(ax.get_yticks(),ax.get_yticklabels()):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,[tick,tick,tick],tickpos2,
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
text3d(ax, (xmin-length*1.1*xlen, tick, zmin), label.get_text(),size=fs_label*minLen_axis,
fc=label.get_color(), ec="None",ha='center',va='top',angle=-90)
label.set_alpha(0)
ax.plot([xmin,xmin-length*xlen],[tick,tick],[zmin,zmin],lw=linewidth,color=label.get_color())
if(label3D):
ax.plot([xmax,xmax],[ymin,ymax],[zmin,zmin],lw=linewidth,color=label.get_color(),ls='dashed')
text3d(ax, (xmin-length*offset_axislabel*xlen,(ymin+ymax)/2, zmin), ax.get_ylabel(),
size=fs_label*minLen_axis, fc=label.get_color(), ec="None",ha='center',va='top',angle=-90)
# z轴
tickmin,tickmax,tickaxis,axislim=zmin,zmax,ax.zaxis,ax.get_zlim()
tickpos1,tickpos2=[xmax,xmax,xmin],[ymin,ymax,ymax]
if(type(length_major)==type([1,1,1])):
length=length_major[2]
for tick,label in zip(ax.get_zticks(),ax.get_zticklabels()):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,tickpos2,[tick,tick,tick],
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
text3d(ax, (xmin-1.1*length*xlen,ymax,tick), label.get_text(),zdir='y',size=fs_label*minLen_axis,
fc=label.get_color(), ec="None",ha='center',va='bottom',angle=90)
label.set_alpha(0)
ax.plot([xmin,xmin-length*minLen_axis],[ymax,ymax],[tick,tick],lw=linewidth,color=label.get_color(),clip_on=False)
if(label3D):
ax.plot([xmin,xmin],[ymax,ymax],[zmin,zmax],lw=linewidth,color=label.get_color())
text3d(ax, (xmin-length*offset_axislabel*xlen,ymax, (zmin+zmax)/2), ax.get_zlabel(),zdir='y',
size=fs_label*minLen_axis, fc=label.get_color(), ec="None",ha='center',va='bottom',angle=90)
if(frame_on==True):
ax.plot([xmax,xmax,xmax,xmin,xmin],[ymin,ymin,ymax,ymax,ymax],[zmin,zmax,zmax,zmax,zmin],color=label.get_color(),lw=linewidth)
ax.plot([xmin,xmin,xmin],[ymin,ymax,ymax],[zmin,zmin,zmax],color=label.get_color(),lw=linewidth)
ax.plot([xmin,xmax],[ymax,ymax],[zmin,zmin],color=label.get_color(),lw=linewidth,ls='dashed')
# 副刻度线
linewidth, color, length = lw_minor, color_minor,length_minor
# x轴
tickmin,tickmax,tickaxis,axislim=xmin,xmax,ax.xaxis,ax.get_xlim()
tickpos1,tickpos2=[ymin,ymax,ymax],[zmin,zmin,zmax]
for tick in tickaxis.get_minor_locator().tick_values(tickmin,tickmax):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot([tick,tick,tick],tickpos1,tickpos2,
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
ax.plot([tick,tick],[ymin,ymin-length*ylen],[zmin,zmin],lw=linewidth,color=label.get_color())
# y轴
tickmin,tickmax,tickaxis,axislim=ymin,ymax,ax.yaxis,ax.get_ylim()
tickpos1,tickpos2=[xmax,xmax,xmin],[zmax,zmin,zmin]
for tick in tickaxis.get_minor_locator().tick_values(tickmin,tickmax):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,[tick,tick,tick],tickpos2,
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
ax.plot([xmin,xmin-length*xlen],[tick,tick],[zmin,zmin],lw=linewidth,color=label.get_color())
# z轴
tickmin,tickmax,tickaxis,axislim=zmin,zmax,ax.zaxis,ax.get_zlim()
tickpos1,tickpos2=[xmax,xmax,xmin],[ymin,ymax,ymax]
for tick in tickaxis.get_minor_locator().tick_values(tickmin,tickmax):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,tickpos2,[tick,tick,tick],
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
ax.plot([xmin,xmin-length*xlen],[ymax,ymax],[tick,tick],lw=linewidth,color=label.get_color(),clip_on=False)
# 3. 设置ticks和labels以及spines和panes
for axis,inward_factor in zip([ax.xaxis,ax.yaxis,ax.zaxis],[0.3,0.2,0.2]):
axis._axinfo['tick']['inward_factor'] = inward_factor
axis._axinfo['tick']['outward_factor'] = 0
ax.tick_params(which='minor', color=(0,0,1,0) ) # 取消副刻度
# xaxis
color,alpha,pad,axis,waxis=(1,0,0),alpha_pane,-3,ax.xaxis,ax.w_xaxis
ax.tick_params(axis='x', which='major', pad=pad)
axis.set_pane_color(color+(alpha,))
axis.pane.set_edgecolor(ec_pane)
axis.pane.fill = fill_pane
waxis.line.set_color(ax.get_xticklines()[0].get_color())
# yaxis
color,alpha,pad,axis,waxis=(0,1,0),alpha_pane,-3,ax.yaxis,ax.w_yaxis
ax.tick_params(axis='y', which='major', pad=pad)
axis.set_pane_color(color+(alpha,))
axis.pane.set_edgecolor(ec_pane)
axis.pane.fill = fill_pane
waxis.line.set_color(ax.get_yticklines()[0].get_color())
# zaxis
color,alpha,pad,axis,waxis=(0,0,1),alpha_pane,0,ax.zaxis,ax.w_zaxis
ax.tick_params(axis='z', which='major', pad=pad)
axis.set_pane_color(color+(alpha,))
axis.pane.set_edgecolor(ec_pane)
axis.pane.fill = fill_pane
waxis.line.set_color(ax.get_zticklines()[0].get_color())
if(label3D):
ax.axis('off')
def niceAxis_3D_loglinearx(ax, data_lim,xcenter, lw_major=0.5,lw_minor=0.25,color_major="0.50",color_minor="0.75",
alpha_pane=0.2,fill_pane=True,ec_pane='None',label3D=True,fs_label=0.1,
length_major=0.05,length_minor=0.02,offset_axislabel=3,frame_on=True,scaled=True,xMajor_loc_log=2,xMinor_loc_log=0.4,xMajor_loc_linear=10,xMinor_loc_linear=2,process_x=False):
color_log,color_linear = 'k','k'
# 坐标轴自定义
xlim,ylim,zlim=ax.get_xlim(),ax.get_ylim(),ax.get_zlim()
xmin,xmax,ymin,ymax,zmin,zmax=xlim[0],xlim[1],ylim[0],ylim[1],zlim[0],zlim[1]
# 1. 根据坐标轴范围设置坐标轴比例:假设xyz三轴以自然比例显示
xlen,ylen,zlen=xmax-xmin, ymax-ymin, zmax-zmin
minLen_axis=np.min([xlen,ylen,zlen])
xratio,yratio,zratio=[xlen,ylen,zlen]/minLen_axis
if(scaled):
ax.set_box_aspect((8*xratio,4*yratio,3*zratio)) # 默认比例是4:4:3
# 3. 重新定义网格线:注意mpl的三维绘图目前不支持grid()函数分别定义主刻度网格和副刻度网格属性
ax.grid(False) # 首先关闭默认网格
zorder_grid=-50
try:
ax.get_figure().draw_without_rendering() # new in 3.5: https://matplotlib.org/stable/users/prev_whats_new/whats_new_3.5.0.html#figure-now-has-draw-without-rendering-method
except:
try:
ax.get_figure().canvas.draw() # Old version
except:
pass
if(ax.get_xticklabels()[0]._text==''): return
# 主刻度线
linewidth, color, length = lw_major, color_major, length_major
if(type(length_major)==type([1,1,1])):
length=length_major[0]
# x轴
if(process_x):
tickmin,tickmax,tickaxis,axislim=xmin,xmax,ax.xaxis,ax.get_xlim()
# log段
xmin_data,xmax_data = np.log10(data_lim[0]),np.log10(xcenter)
xMajorLocator = mpl.ticker.MultipleLocator(xMajor_loc_log).tick_values(xmin_data,xmax_data)
# 计算tick在坐标轴上的真正位置,将数据范围投影到坐标轴范围中
xmin_axis,xmax_axis=ax.get_xlim()[0],0
length_ = xmax_axis- xmin_axis
scale_data2axes = length_/(xmax_data - xmin_data)
tickpos1,tickpos2=[ymin,ymax,ymax],[zmin,zmin,zmax]
for tick_data in xMajorLocator:
if((tick_data<xmin_data) | (tick_data>xmax_data)):
continue
tick = (tick_data-xmin_data)*scale_data2axes + xmin_axis
ticklabel = '10$^{\mathregular{%d}}$'%(tick_data)
ax.plot([tick,tick,tick],tickpos1,tickpos2, lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
text3d(ax, (tick, ymin-length*1.2*ylen, zmin), ticklabel,size=fs_label*minLen_axis, fc=color_log, ec="None", ha='center',va='top')
ax.plot([tick,tick],[ymin,ymin-length*ylen],[zmin,zmin],lw=linewidth,color=color_log)
# linear和log的分界线
# ax.plot([0,0],[ymin,ymax],[zmin,zmin],lw=linewidth,color='r')
if(label3D):
ax.plot([xmin_axis,xmax_axis],[ymin,ymin],[zmin,zmin],lw=linewidth,color=color_log)
text3d(ax, ((xmin_axis+xmax_axis)/2, ymin-length*offset_axislabel*1.3*ylen, zmin), 'log scale',
size=fs_label*minLen_axis, fc=color_log, ec="None",ha='center',va='top')
# linear段
xmin_data,xmax_data = xcenter,data_lim[1]
xMajorLocator = mpl.ticker.MultipleLocator(xMajor_loc_linear).tick_values(xmin_data,xmax_data)
# 计算tick在坐标轴上的真正位置,将数据范围投影到坐标轴范围中
xmin_axis,xmax_axis=0,ax.get_xlim()[1]
length_ = xmax_axis- xmin_axis
scale_data2axes = length_/(xmax_data - xmin_data)
tickpos1,tickpos2=[ymin,ymax,ymax],[zmin,zmin,zmax]
for tick_data in xMajorLocator:
if((tick_data<xmin_data) | (tick_data>xmax_data)):
continue
tick = (tick_data-xmin_data)*scale_data2axes + xmin_axis
ticklabel = '%.0f'%(tick_data)
ax.plot([tick,tick,tick],tickpos1,tickpos2, lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
text3d(ax, (tick, ymin-length*1.2*ylen, zmin), ticklabel,size=fs_label*minLen_axis, fc=color_linear, ec="None", ha='center',va='top')
ax.plot([tick,tick],[ymin,ymin-length*ylen],[zmin,zmin],lw=linewidth,color=color_linear)
# linear和log的分界线
ax.plot([0,0],[ymin,ymax],[zmin,zmin],lw=linewidth,color='k')
if(label3D):
ax.plot([xmin_axis,xmax_axis],[ymin,ymin],[zmin,zmin],lw=linewidth,color=color_linear)
text3d(ax, ((xmin_axis+xmax_axis)/2, ymin-length*offset_axislabel*1.3*ylen, zmin), 'linear scale',
size=fs_label*minLen_axis, fc=color_linear, ec="None",ha='center',va='top')
# 总的xlabel
text3d(ax, ((ax.get_xlim()[0]+ax.get_xlim()[1])/2, ymin-length*offset_axislabel*1.5*ylen, zmin), ax.get_xlabel(),
size=fs_label*minLen_axis, fc='k', ec="None",ha='center',va='top')
# y轴
tickmin,tickmax,tickaxis,axislim=ymin,ymax,ax.yaxis,ax.get_ylim()
tickpos1,tickpos2=[xmax,xmax,xmin],[zmax,zmin,zmin]
if(type(length_major)==type([1,1,1])):
length=length_major[1]
for tick,label in zip(ax.get_yticks(),ax.get_yticklabels()):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,[tick,tick,tick],tickpos2,
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
text3d(ax, (xmin-length*1.1*xlen, tick, zmin), label.get_text(),size=fs_label*minLen_axis,
fc=label.get_color(), ec="None",ha='center',va='top',angle=-90)
label.set_alpha(0)
ax.plot([xmin,xmin-length*xlen],[tick,tick],[zmin,zmin],lw=linewidth,color=label.get_color())
if(label3D):
ax.plot([xmax,xmax],[ymin,ymax],[zmin,zmin],lw=linewidth,color=label.get_color(),ls='dashed')
text3d(ax, (xmin-length*offset_axislabel*xlen,(ymin+ymax)/2, zmin), ax.get_ylabel(),
size=fs_label*minLen_axis, fc=label.get_color(), ec="None",ha='center',va='top',angle=-90)
# z轴
tickmin,tickmax,tickaxis,axislim=zmin,zmax,ax.zaxis,ax.get_zlim()
tickpos1,tickpos2=[xmax,xmax,xmin],[ymin,ymax,ymax]
if(type(length_major)==type([1,1,1])):
length=length_major[2]
for tick,label in zip(ax.get_zticks(),ax.get_zticklabels()):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,tickpos2,[tick,tick,tick],
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
text3d(ax, (xmin-1.1*length*xlen,ymax,tick), label.get_text(),zdir='y',size=fs_label*minLen_axis,
fc=label.get_color(), ec="None",ha='center',va='bottom',angle=90)
label.set_alpha(0)
ax.plot([xmin,xmin-length*minLen_axis],[ymax,ymax],[tick,tick],lw=linewidth,color=label.get_color(),clip_on=False)
if(label3D):
ax.plot([xmin,xmin],[ymax,ymax],[zmin,zmax],lw=linewidth,color=label.get_color())
text3d(ax, (xmin-length*offset_axislabel*xlen,ymax, (zmin+zmax)/2), ax.get_zlabel(),zdir='y',
size=fs_label*minLen_axis, fc=label.get_color(), ec="None",ha='center',va='bottom',angle=90)
if(frame_on==True):
ax.plot([xmax,xmax,xmax,xmin,xmin],[ymin,ymin,ymax,ymax,ymax],[zmin,zmax,zmax,zmax,zmin],color=label.get_color(),lw=linewidth)
ax.plot([xmin,xmin,xmin],[ymin,ymax,ymax],[zmin,zmin,zmax],color=label.get_color(),lw=linewidth)
ax.plot([xmin,xmax],[ymax,ymax],[zmin,zmin],color=label.get_color(),lw=linewidth,ls='dashed')
# 副刻度线
linewidth, color, length = lw_minor, color_minor,length_minor
# x轴
if(process_x):
tickmin,tickmax,tickaxis,axislim=xmin,xmax,ax.xaxis,ax.get_xlim()
# log段
if(xMajor_loc_log==1):
xmin_data,xmax_data = np.log10(data_lim[0]),np.log10(xcenter)
xMajorLocator = mpl.ticker.MultipleLocator(xMajor_loc_log).tick_values(xmin_data,xmax_data)
# 计算tick在坐标轴上的真正位置,将数据范围投影到坐标轴范围中
xmin_axis,xmax_axis=ax.get_xlim()[0],0
length_ = xmax_axis- xmin_axis
scale_data2axes = length_/(xmax_data - xmin_data)
tickpos1,tickpos2=[ymin,ymax,ymax],[zmin,zmin,zmax]
for tick_data in xMajorLocator:
for ii in np.log10(range(1,10)):
minortick_data = tick_data+ii
if((minortick_data<xmin_data) | (minortick_data>xmax_data)):
continue
tick = (minortick_data-xmin_data)*scale_data2axes + xmin_axis
# ax.plot([tick,tick,tick],tickpos1,tickpos2, lw=linewidth,color=color,zorder=zorder_grid)
ax.plot([tick,tick],[ymin,ymin-length*ylen],[zmin,zmin],lw=linewidth,color='k')
# linear段
xmin_data,xmax_data = xcenter,data_lim[1]
xMajorLocator = mpl.ticker.MultipleLocator(xMajor_loc_linear).tick_values(xmin_data,xmax_data)
xMinorLocator = mpl.ticker.MultipleLocator(xMinor_loc_linear).tick_values(xmin_data,xmax_data)
# 计算tick在坐标轴上的真正位置,将数据范围投影到坐标轴范围中
xmin_axis,xmax_axis=0,ax.get_xlim()[1]
length_ = xmax_axis- xmin_axis
scale_data2axes = length_/(xmax_data - xmin_data)
tickpos1,tickpos2=[ymin,ymax,ymax],[zmin,zmin,zmax]
for tick_data in xMinorLocator:
if((tick_data<xmin_data) | (tick_data>xmax_data) | (tick_data in xMajorLocator)):
continue
tick = (tick_data-xmin_data)*scale_data2axes + xmin_axis
ax.plot([tick,tick,tick],tickpos1,tickpos2, lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
ax.plot([tick,tick],[ymin,ymin-length*ylen],[zmin,zmin],lw=linewidth,color='k')
# y轴
tickmin,tickmax,tickaxis,axislim=ymin,ymax,ax.yaxis,ax.get_ylim()
tickpos1,tickpos2=[xmax,xmax,xmin],[zmax,zmin,zmin]
for tick in tickaxis.get_minor_locator().tick_values(tickmin,tickmax):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,[tick,tick,tick],tickpos2,
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
ax.plot([xmin,xmin-length*xlen],[tick,tick],[zmin,zmin],lw=linewidth,color=label.get_color())
# z轴
tickmin,tickmax,tickaxis,axislim=zmin,zmax,ax.zaxis,ax.get_zlim()
tickpos1,tickpos2=[xmax,xmax,xmin],[ymin,ymax,ymax]
for tick in tickaxis.get_minor_locator().tick_values(tickmin,tickmax):
if((tick<axislim[0]) | (tick>axislim[1])):
continue
ax.plot(tickpos1,tickpos2,[tick,tick,tick],
lw=linewidth,color=color,zorder=zorder_grid)
if(label3D):
ax.plot([xmin,xmin-length*xlen],[ymax,ymax],[tick,tick],lw=linewidth,color=label.get_color(),clip_on=False)
# 3. 设置ticks和labels以及spines和panes
for axis,inward_factor in zip([ax.xaxis,ax.yaxis,ax.zaxis],[0.3,0.2,0.2]):
axis._axinfo['tick']['inward_factor'] = inward_factor
axis._axinfo['tick']['outward_factor'] = 0
ax.tick_params(which='minor', color=(0,0,1,0) ) # 取消副刻度
# xaxis
if(process_x):
color,alpha,pad,axis,waxis=(1,0,0),alpha_pane,-3,ax.xaxis,ax.w_xaxis
ax.tick_params(axis='x', which='major', pad=pad)
axis.set_pane_color(color+(alpha,))
axis.pane.set_edgecolor(ec_pane)
axis.pane.fill = fill_pane
waxis.line.set_color(ax.get_xticklines()[0].get_color())
# yaxis
color,alpha,pad,axis,waxis=(0,1,0),alpha_pane,-3,ax.yaxis,ax.w_yaxis
ax.tick_params(axis='y', which='major', pad=pad)
axis.set_pane_color(color+(alpha,))
axis.pane.set_edgecolor(ec_pane)
axis.pane.fill = fill_pane
waxis.line.set_color(ax.get_yticklines()[0].get_color())
# zaxis
color,alpha,pad,axis,waxis=(0,0,1),alpha_pane,0,ax.zaxis,ax.w_zaxis
ax.tick_params(axis='z', which='major', pad=pad)
axis.set_pane_color(color+(alpha,))
axis.pane.set_edgecolor(ec_pane)
axis.pane.fill = fill_pane
waxis.line.set_color(ax.get_zticklines()[0].get_color())
if(label3D):
ax.axis('off')
def set_axis_diagram_3D(ax,xlim=(0,100),ylim=(0,1000),zlim=(0,2500),xMajor_loc=10,xMinor_loc=2,yMajor_loc=100,yMinor_loc=20,zMajor_loc=500,zMinor_loc=100,xlabel="Wt.% NaCl",ylabel="Temperature ($^{\circ}$C)",zlabel="Pressure (bar)"):
ax.set_ylabel(ylabel)
ax.set_xlabel(xlabel)
ax.set_zlabel(zlabel)
ax.set_ylim(ylim)
ax.set_xlim(xlim)
ax.set_zlim(zlim)
# 设置坐标轴刻度间隔
ax.xaxis.set_major_locator(MultipleLocator(xMajor_loc))
ax.xaxis.set_minor_locator(MultipleLocator(xMinor_loc))
ax.yaxis.set_major_locator(MultipleLocator(yMajor_loc))
ax.yaxis.set_minor_locator(MultipleLocator(yMinor_loc))
ax.zaxis.set_major_locator(MultipleLocator(zMajor_loc))
ax.zaxis.set_minor_locator(MultipleLocator(zMinor_loc))
# 重新自定义坐标轴属性
niceAxis_3D(ax,fill_pane=False,label3D=True,fs_label=0.024,length_major=0.02,length_minor=0.01, scaled=False)
# ax.legend()
ax.view_init(elev=25, azim=-145)
def set_axis_diagram_3D_loglinearx(ax,xcenter=1,ratio_log_lin=(1,1),xlim=(1E-14,100),ylim=(0,1000),zlim=(0,2500),xMajor_loc_log=10,xMinor_loc_log=2,xMajor_loc_linear=10,xMinor_loc_linear=2,yMajor_loc=100,yMinor_loc=20,zMajor_loc=500,zMinor_loc=100,xlabel="Wt.% NaCl",ylabel="Temperature ($^{\circ}$C)",zlabel="Pressure (bar)"):
ax.set_box_aspect((8,4,3))
ax.set_ylabel(ylabel)
ax.set_xlabel(xlabel)
ax.set_zlabel(zlabel)
ax.set_ylim(ylim)
# 把x轴的范围投影到-1,1之间
data_lim = xlim
ax.set_xlim((-ratio_log_lin[0]/ratio_log_lin[1],1))
ax.set_zlim(zlim)
# 设置坐标轴刻度间隔
# ax.xaxis.set_major_locator(MultipleLocator(xMajor_loc))
# ax.xaxis.set_minor_locator(MultipleLocator(xMinor_loc))
ax.yaxis.set_major_locator(MultipleLocator(yMajor_loc))
ax.yaxis.set_minor_locator(MultipleLocator(yMinor_loc))
ax.zaxis.set_major_locator(MultipleLocator(zMajor_loc))
ax.zaxis.set_minor_locator(MultipleLocator(zMinor_loc))
# 重新自定义坐标轴属性
# 设置yz轴
niceAxis_3D_loglinearx(ax,data_lim,xcenter=xcenter,fill_pane=False,label3D=True,fs_label=0.024,length_major=0.02,length_minor=0.01, scaled=False, process_x=False)
# 专门处理x轴
ax.set_xlabel(xlabel)
niceAxis_3D_loglinearx(ax,data_lim,xcenter=xcenter,xMajor_loc_log=xMajor_loc_log,xMinor_loc_log=xMinor_loc_log,xMajor_loc_linear=xMajor_loc_linear,xMinor_loc_linear=xMinor_loc_linear,
fill_pane=False,label3D=True,fs_label=0.024,length_major=0.02,length_minor=0.01, scaled=False, process_x=True)
# ax.legend()
ax.view_init(elev=25, azim=-145)
return {'xlim':xlim,'xcenter':xcenter,'ratio_log_lin':ratio_log_lin}
# transform original data to log-linear axis data
def data2axis_loglin(axtrans,x):
x_new = x*0
if(type(x)==type(np.linspace(0,1,2))): # array
ind_log=(x<=axtrans['xcenter'])
ind_linear=(x>axtrans['xcenter'])
# linear part
xmin=axtrans['xcenter']
xmax=axtrans['xlim'][1]
x_new[ind_linear] = (x[ind_linear]-xmin)/(xmax-xmin)
# log part
xmin=np.log10(axtrans['xlim'][0])
xmax=np.log10(axtrans['xcenter'])
x_log=np.log10(x)
x_new[ind_log] = (x_log[ind_log]-xmax)/(xmax-xmin)
else: # number
if(x<=axtrans['xcenter']):
# log part
xmin=np.log10(axtrans['xlim'][0])
xmax=np.log10(axtrans['xcenter'])
x_log=np.log10(x)
x_new = (x_log-xmax)/(xmax-xmin)
elif(x>axtrans['xcenter']):
# linear part
xmin=axtrans['xcenter']
xmax=axtrans['xlim'][1]
x_new = (x-xmin)/(xmax-xmin)
return x_new
def plot_coloredline(ax,x,y,data,cmap='YlGnBu',lw=4):
points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
norm = plt.Normalize(data.min(), data.max())
lc = LineCollection(segments, cmap=cmap, norm=norm)
lc.set_array(data)
lc.set_linewidth(lw)
line = ax.add_collection(lc)
return line
def plot_coloredline(ax,x,y,data,vmin=None,vmax=None,cmap='YlGnBu',lw=4):
points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
if(vmin is None): vmin = data.min()
if(vmax is None): vmax = data.max()
norm = plt.Normalize(vmin,vmax)
lc = LineCollection(segments, cmap=cmap, norm=norm)
lc.set_array(data)
lc.set_linewidth(lw)
line = ax.add_collection(lc)
return line
Total running time of the script: ( 0 minutes 0.000 seconds)