我想在下面的(其他)空图中添加一个比例指示器,如标题为“10kpc”的图表。基本上,轴使用一个度量单位,我想用不同的单位表示图中的长度。它必须具有与下面相同的样式,即| ---- |酒吧上面有文字。
在matplotlib中有没有方便的方法来做或者我必须画三条线(两条小垂直,一条水平)并添加文字?一个理想的解决方案甚至不需要我在数据维度中设置坐标,即我只是在horizontalalignment='left', verticalalignment='bottom', transform=ax.transAxes
的行上说一些东西,并且只指定数据坐标中的宽度。
我与annotate()
和arrow()
以及他们的文件进行了一段时间的争吵,直到我得出结论,它们并不完全有用,但我可能错了。
修改
下面的代码是最接近的,我到目前为止。我仍然不喜欢在数据坐标系中指定x坐标。我想在数据中指定的唯一内容是条的宽度。其余的应该放在绘图系统中,理想情况下应该相对于文本放置条形图(上面几个像素)。
import matplotlib.pyplot as plt
import matplotlib.transforms as tfrms
plt.imshow(somedata)
plt.colorbar()
ax = plt.gca()
trans = tfrms.blended_transform_factory( ax.transData, ax.transAxes )
plt.errorbar( 5, 0.06, xerr=10*arcsecperkpc/2, color='k', capsize=5, transform=trans )
plt.text( 5, 0.05, '10kpc', horizontalalignment='center', verticalalignment='top', transform=trans )
答案 0 :(得分:2)
这是一个代码,用于向绘图添加水平比例尺(或比例指示器或比例尺)。条的宽度以数据单位给出,而边的高度以轴单位的分数表示。
该解决方案基于AnchoredOffsetbox
,其中包含VPacker
。 VPacker
的下排有一个标签,上排有一个AuxTransformBox
这里的关键是AnchoredOffsetbox
相对于轴定位,使用类似于图例定位的loc
参数(例如loc=4
表示右下角)。但是,AuxTransformBox
包含一组元素,这些元素使用转换位于框内。作为变换,我们可以根据轴变换选择根据轴和y坐标的数据变换来变换x坐标的混合变换。执行此操作的转换实际上是轴本身的xaxis_transform。将此变换提供给AuxTransformBox
允许我们以有用的方式指定其中的艺术家(在这种情况下为Line2D
),例如栏的行将是Line2D([0,size],[0,0])
。
所有这些都可以打包到一个类中,对AnchoredOffsetbox
进行子类化,这样就很容易在现有代码中使用。
import matplotlib.pyplot as plt
import matplotlib.offsetbox
from matplotlib.lines import Line2D
import numpy as np; np.random.seed(42)
x = np.linspace(-6,6, num=100)
y = np.linspace(-10,10, num=100)
X,Y = np.meshgrid(x,y)
Z = np.sin(X)/X+np.sin(Y)/Y
fig, ax = plt.subplots()
ax.contourf(X,Y,Z, alpha=.1)
ax.contour(X,Y,Z, alpha=.4)
class AnchoredHScaleBar(matplotlib.offsetbox.AnchoredOffsetbox):
""" size: length of bar in data units
extent : height of bar ends in axes units """
def __init__(self, size=1, extent = 0.03, label="", loc=2, ax=None,
pad=0.4, borderpad=0.5, ppad = 0, sep=2, prop=None,
frameon=True, **kwargs):
if not ax:
ax = plt.gca()
trans = ax.get_xaxis_transform()
size_bar = matplotlib.offsetbox.AuxTransformBox(trans)
line = Line2D([0,size],[0,0], **kwargs)
vline1 = Line2D([0,0],[-extent/2.,extent/2.], **kwargs)
vline2 = Line2D([size,size],[-extent/2.,extent/2.], **kwargs)
size_bar.add_artist(line)
size_bar.add_artist(vline1)
size_bar.add_artist(vline2)
txt = matplotlib.offsetbox.TextArea(label, minimumdescent=False)
self.vpac = matplotlib.offsetbox.VPacker(children=[size_bar,txt],
align="center", pad=ppad, sep=sep)
matplotlib.offsetbox.AnchoredOffsetbox.__init__(self, loc, pad=pad,
borderpad=borderpad, child=self.vpac, prop=prop, frameon=frameon)
ob = AnchoredHScaleBar(size=3, label="3 units", loc=4, frameon=True,
pad=0.6,sep=4,color="crimson")
ax.add_artist(ob)
plt.show()
为了在问题中获得所需的结果,您可以关闭帧并调整线宽。当然,从想要显示的单位(kpc)到数据单位(km?)的转换需要由你自己完成。
ikpc = lambda x: x*3.085e16 #x in kpc, return in km
ob = AnchoredHScaleBar(size=ikpc(10), label="10kpc", loc=4, frameon=False,
pad=0.6,sep=4,color="k", linewidth=0.8)