2017-10-21 57 views
0

我在我的“现实世界”问题中,我想重新计算写入我的图形的刻度标记后的xy值,原点总是在(0,0)处,显然x和y轴上的值的相对距离保持不变。 我的问题解决了这一主题: Initial solution创建一个颜色条将两个以前对齐的轴对象相对移动 - Matplotlib

该解决方案包括持有的情节和变焦后得到不同的刻度标贴一个可见轴一个看不见的轴的创建。

在我的情况下,我想叠加多个countor和coutourf情节。对于这些情节中只有一个,我想向该图添加一个颜色条! 但是当我在脚本中创建颜色条时,我创建的两个轴对象相对于彼此相对移动。没有彩条,他们是完全对齐的!

这里是大致再现行为的MWE:

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib import mlab, cm 

# Default delta is large because that makes it fast, and it illustrates 
# the correct registration between image and contours. 
delta = 0.5 

extent = (-3, 4, -4, 3) 

x = np.arange(-3.0, 4.001, delta) 
y = np.arange(-4.0, 3.001, delta) 
X, Y = np.meshgrid(x, y) 
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) 
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) 
Z = (Z1 - Z2) * 10 

levels = np.arange(-2.0, 1.601, 0.4) # Boost the upper limit to avoid truncation errors. 

norm = cm.colors.Normalize(vmax=abs(Z).max(), vmin=-abs(Z).max()) 
cmap = cm.PRGn 




# ax is empty 
fig, ax = plt.subplots() 
ax.set_navigate(False) 
# ax2 will hold the plot, but has invisible labels 
ax2 = fig.add_subplot(111,zorder=2) 

ax2.contourf(X, Y, Z, levels, 
       cmap=cm.get_cmap(cmap, len(levels) - 1), 
       norm=norm, 
       ) 
ax2.axis("off") 

ax.set_xlim(ax2.get_xlim()) 
ax.set_ylim(ax2.get_ylim()) 

# 
# Declare and register callbacks 
def on_lims_change(axes): 
    # change limits of ax, when ax2 limits are changed. 
    a=ax2.get_xlim() 
    ax.set_xlim(0, a[1]-a[0]) 
    a=ax2.get_ylim() 
    ax.set_ylim(0, a[1]-a[0]) 



sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) #Do not show unnecessary parts of the colormap 
sm._A = [] 
cb = plt.colorbar(sm,extend="both", label="units") 
cb.ax.tick_params(labelsize=10) 


ax2.callbacks.connect('xlim_changed', on_lims_change) 
ax2.callbacks.connect('ylim_changed', on_lims_change) 
ax.axis('scaled') 
plt.axis('scaled') 
# Show 
plt.show() 

现在contourplot似乎转移到realtive可见轴。我找到了一些线索在网上暗示,即“彩条框会自动吃掉从轴的空间,其附着” Link1 Link2

但我真的不知道我需要做些什么来改变这种行为如果我的问题是相关的,我也不理解。

请注意,部分:

ax.axis('scaled') 
plt.axis('scaled') 

是必要的,因为我需要保持宽高比酷似它在数据集!

预先感谢您!

回答

1

可以经由

ax.set_position(ax2.get_position()) 

可选地添加颜色条后更改的ax(有标签的空轴)至ax2位置的位置(坐标轴示出了数据),创建以“彩条钢“的空间,

cb = fig.colorbar(sm,ax=[ax,ax2], extend="both", label="units") 

这两个解决方案都可以在this linked question的答案中找到。


以下是这个问题的实际范围之外的一些额外的改进:

ax.axis('scaled') 
ax2.axis('scaled') 

此外,把ax在顶部,如果ax2,使得contourf情节不重叠的轴刺。

# put `ax` on top, to let the contours not overlap the shown axes 
ax.set_zorder(2)  
ax.patch.set_visible(False) 
# ax2 will hold the plot, but has invisible labels 
ax2 = fig.add_subplot(111,zorder=1) 

完整代码:

import matplotlib.pyplot as plt 
import numpy as np 
from matplotlib import mlab, cm 

delta = 0.5 
extent = (-3, 4, -4, 3) 
x = np.arange(-3.0, 4.001, delta) 
y = np.arange(-4.0, 3.001, delta) 
X, Y = np.meshgrid(x, y) 
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) 
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) 
Z = (Z1 - Z2) * 10 

levels = np.arange(-2.0, 1.601, 0.4) 

norm = cm.colors.Normalize(vmax=abs(Z).max(), vmin=-abs(Z).max()) 
cmap = cm.PRGn 

# ax is empty 
fig, ax = plt.subplots() 
ax.set_navigate(False) 
# put `ax` on top, to let the contours not overlap the shown axes 
ax.set_zorder(2)  
ax.patch.set_visible(False) 
# ax2 will hold the plot, but has invisible labels 
ax2 = fig.add_subplot(111,zorder=1) 

ax2.contourf(X, Y, Z, levels, 
       cmap=cm.get_cmap(cmap, len(levels) - 1), 
       norm=norm, 
       ) 
ax2.axis("off") 

ax.set_xlim(ax2.get_xlim()) 
ax.set_ylim(ax2.get_ylim()) 

# 
# Declare and register callbacks 
def on_lims_change(axes): 
    # change limits of ax, when ax2 limits are changed. 
    a=ax2.get_xlim() 
    ax.set_xlim(0, a[1]-a[0]) 
    a=ax2.get_ylim() 
    ax.set_ylim(0, a[1]-a[0]) 


sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm) 
sm._A = [] 
cb = fig.colorbar(sm,ax=[ax,ax2], extend="both", label="units") 
cb.ax.tick_params(labelsize=10) 

ax2.callbacks.connect('xlim_changed', on_lims_change) 
ax2.callbacks.connect('ylim_changed', on_lims_change) 
ax.axis('scaled') 
ax2.axis('scaled') 
#ax.set_position(ax2.get_position()) 
# Show 
plt.show() 

enter image description here

+0

我试图执行没有成功这凸显我缺乏了解的线程解决方案。我现在面临的问题是,如果我想像这样'circle = Circle(( - 3,2),0.1,color ='r')ax2.add_patch(circle)''添加'matplotlib.patches'。当补丁添加到绘图的边缘时,显示的X-Y范围会更改以显示整个圆和坐标移位。这与'ax.axis'('scaled')的调用有关ax2.axis('scaled')'....我希望看到一个提示,因为我找不到任何东西,当我搜索它。感谢您的解决方案!它真的很感激! – NorrinRadd

+0

在调用'ax.set_xlim(ax2.get_xlim())'之前,您需要添加圆圈(或者任何东西)*。 – ImportanceOfBeingErnest

+0

我知道这个社区有点夸张地表达了我的感谢......但我真的想给你买一杯啤酒或其他东西......这解决了我眼前的一个问题!谢谢! – NorrinRadd