gpt4 book ai didi

python - Matplotlib 轴标签 : how to find out where they will be located?

转载 作者:太空狗 更新时间:2023-10-30 00:03:31 26 4
gpt4 key购买 nike

我编写了一个例程来根据大气模型输出绘制垂直横截面。一个例子如下所示。我想做的是显示两个垂直轴:在左侧,我以对数刻度显示压力值,在右侧,我以公里为单位显示高度。我认为在模型级别的位置显示高度会很好 - 这就是它们不规则间隔的原因。一切都很好,除了右边的标签在底部附近重叠。我发现我可以使用 ax2.get_yticklabels()[index].set_visible(False) 隐藏特定标签。我的问题是:如何确定要隐藏哪些标签(索引)?我相信应该可以找出刻度标签的位置(在轴或图形坐标中)。然后我可以使用阈值距离,如

yp = -1  
for t in ax2.get_yticklabels():
y = t.get_position().y0 # this doesn't yield any useful bbox!
if y-yp < threshold:
t.set_visible(False)
else:
yp = y

不幸的是,我还没有找到获取标签坐标的方法。有什么提示吗?

这是示例图: Vertical cross section plot

下面是完成绘图的完整代码(数据是二维数组,x 是纬度,y 是压力值):

def plotZM(data, x, y, plotOpt=None):
"""Create a zonal mean contour plot of one variable
plotOpt is a dictionary with plotting options:
'scale_factor': multiply values with this factor before plotting
'units': a units label for the colorbar
'levels': use list of values as contour intervals
'title': a title for the plot
"""
if plotOpt is None: plotOpt = {}
# create figure and axes
fig = plt.figure()
ax1 = fig.add_subplot(111)
# scale data if requested
scale_factor = plotOpt.get('scale_factor', 1.0)
pdata = data * scale_factor
# determine contour levels to be used; default: linear spacing, 20 levels
clevs = plotOpt.get('levels', np.linspace(data.min(), data.max(), 20))
# map contour values to colors
norm=matplotlib.colors.BoundaryNorm(clevs, ncolors=256, clip=False)
# draw the (filled) contours
contour = ax1.contourf(x, y, pdata, levels=clevs, norm=norm)
# add a title
title = plotOpt.get('title', 'Vertical cross section')
ax1.set_title(title) # optional keyword: fontsize="small"
# add colorbar
# Note: use of the ticks keyword forces colorbar to draw all labels
fmt = matplotlib.ticker.FormatStrFormatter("%g")
cbar = fig.colorbar(contour, ax=ax1, orientation='horizontal', shrink=0.8,
ticks=clevs, format=fmt)
cbar.set_label(plotOpt.get('units', ''))
for t in cbar.ax.get_xticklabels():
t.set_fontsize("x-small")
# change font size of x labels
xlabels = ax1.get_xticklabels()
for t in xlabels:
t.set_fontsize("x-small")
# set up y axes: log pressure labels on the left y axis, altitude labels
# according to model levels on the right y axis
ax1.set_ylabel("Pressure [hPa]")
ax1.set_yscale('log')
ax1.set_ylim(y.max(), y.min())
subs = [1,2,5]
print "y_max/y_min = ", y.max()/y.min()
if y.max()/y.min() < 30.:
subs = [1,2,3,4,5,6,7,8,9]
loc = matplotlib.ticker.LogLocator(base=10., subs=subs)
ax1.yaxis.set_major_locator(loc)
fmt = matplotlib.ticker.FormatStrFormatter("%g")
ax1.yaxis.set_major_formatter(fmt)
ylabels = ax1.get_yticklabels()
for t in ylabels:
t.set_fontsize("x-small")
# calculate altitudes from pressure values (use fixed scale height)
z0 = 8.400 # scale height for pressure_to_altitude conversion [km]
altitude = z0 * np.log(1015.23/y)
# add second y axis for altitude scale
ax2 = ax1.twinx()
ax2.set_ylabel("Altitude [km]")
ax2.set_ylim(altitude.min(), altitude.max())
ax2.set_yticks(altitude)
fmt = matplotlib.ticker.FormatStrFormatter("%6.1f")
ax2.yaxis.set_major_formatter(fmt)
# tweak altitude labels
ylabels = ax2.get_yticklabels()
for i,t in enumerate(ylabels):
t.set_fontsize("x-small")
# show plot
plt.show()

最佳答案

这是 plotZM 例程的更新版本,它将模型级别绘制到右侧的单独面板中,并使用线性等距标记作为高度轴。添加了另一个选项来屏蔽低于表面压力的区域。

此代码是“缩放安全”的(即,当您放大或平移绘图时,高度和压力标签会发生很好的变化,并且模型级别会持续变化)。它还包含相当多的轴和标签调整,因此可能希望对其他人有用,作为您可以使用 matplotlib 做什么的更复杂的示例。示例图如下所示。

def plotZM(data, x, y, plotOpt=None, modelLevels=None, surfacePressure=None):
"""Create a zonal mean contour plot of one variable
plotOpt is a dictionary with plotting options:
'scale_factor': multiply values with this factor before plotting
'units': a units label for the colorbar
'levels': use list of values as contour intervals
'title': a title for the plot
modelLevels: a list of pressure values indicating the model vertical resolution. If present,
a small side panel will be drawn with lines for each model level
surfacePressure: a list (dimension len(x)) of surface pressure values. If present, these will
be used to mask out regions below the surface
"""
# explanation of axes:
# ax1: primary coordinate system latitude vs. pressure (left ticks on y axis)
# ax2: twinned axes for altitude coordinates on right y axis
# axm: small side panel with shared y axis from ax2 for display of model levels
# right y ticks and y label will be drawn on axr if modelLevels are given, else on ax2
# axr: pointer to "right axis", either ax2 or axm

if plotOpt is None: plotOpt = {}
labelFontSize = "small"
# create figure and axes
fig = plt.figure()
ax1 = fig.add_subplot(111)
# scale data if requested
scale_factor = plotOpt.get('scale_factor', 1.0)
pdata = data * scale_factor
# determine contour levels to be used; default: linear spacing, 20 levels
clevs = plotOpt.get('levels', np.linspace(data.min(), data.max(), 20))
# map contour values to colors
norm=matplotlib.colors.BoundaryNorm(clevs, ncolors=256, clip=False)
# draw the (filled) contours
contour = ax1.contourf(x, y, pdata, levels=clevs, norm=norm)
# mask out surface pressure if given
if not surfacePressure is None:
ax1.fill_between(x, surfacePressure, surfacePressure.max(), color="white")
# add a title
title = plotOpt.get('title', 'Vertical cross section')
ax1.set_title(title)
# add colorbar
# Note: use of the ticks keyword forces colorbar to draw all labels
fmt = matplotlib.ticker.FormatStrFormatter("%g")
cbar = fig.colorbar(contour, ax=ax1, orientation='horizontal', shrink=0.8,
ticks=clevs, format=fmt)
cbar.set_label(plotOpt.get('units', ''))
for t in cbar.ax.get_xticklabels():
t.set_fontsize(labelFontSize)
# set up y axes: log pressure labels on the left y axis, altitude labels
# according to model levels on the right y axis
ax1.set_ylabel("Pressure [hPa]")
ax1.set_yscale('log')
ax1.set_ylim(10.*np.ceil(y.max()/10.), y.min()) # avoid truncation of 1000 hPa
subs = [1,2,5]
if y.max()/y.min() < 30.:
subs = [1,2,3,4,5,6,7,8,9]
y1loc = matplotlib.ticker.LogLocator(base=10., subs=subs)
ax1.yaxis.set_major_locator(y1loc)
fmt = matplotlib.ticker.FormatStrFormatter("%g")
ax1.yaxis.set_major_formatter(fmt)
for t in ax1.get_yticklabels():
t.set_fontsize(labelFontSize)
# calculate altitudes from pressure values (use fixed scale height)
z0 = 8.400 # scale height for pressure_to_altitude conversion [km]
altitude = z0 * np.log(1015.23/y)
# add second y axis for altitude scale
ax2 = ax1.twinx()
# change values and font size of x labels
ax1.set_xlabel('Latitude [degrees]')
xloc = matplotlib.ticker.FixedLocator(np.arange(-90.,91.,30.))
ax1.xaxis.set_major_locator(xloc)
for t in ax1.get_xticklabels():
t.set_fontsize(labelFontSize)
# draw horizontal lines to the right to indicate model levels
if not modelLevels is None:
pos = ax1.get_position()
axm = fig.add_axes([pos.x1,pos.y0,0.02,pos.height], sharey=ax2)
axm.set_xlim(0., 1.)
axm.xaxis.set_visible(False)
modelLev = axm.hlines(altitude, 0., 1., color='0.5')
axr = axm # specify y axis for right tick marks and labels
# turn off tick labels of ax2
for t in ax2.get_yticklabels():
t.set_visible(False)
label_xcoor = 3.7
else:
axr = ax2
label_xcoor = 1.05
axr.set_ylabel("Altitude [km]")
axr.yaxis.set_label_coords(label_xcoor, 0.5)
axr.set_ylim(altitude.min(), altitude.max())
yrloc = matplotlib.ticker.MaxNLocator(steps=[1,2,5,10])
axr.yaxis.set_major_locator(yrloc)
axr.yaxis.tick_right()
for t in axr.yaxis.get_majorticklines():
t.set_visible(False)
for t in axr.get_yticklabels():
t.set_fontsize(labelFontSize)
# show plot
plt.show()

vertical cross section plot with modified code

关于python - Matplotlib 轴标签 : how to find out where they will be located?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14153816/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com