2017-04-06 8 views
1

私は、以下の(そうでない)空のプロットに '10kpc'というラベルのようなプロットにスケールインジケータを追加したいと思います。基本的に、軸は1単位の単位を使用していますので、別の単位でプロットの長さを指定したいと考えています。それは以下のような同じスタイル、すなわちa | ---- |を持っていなければなりません。上のテキストのバー。matplotlibのプロットにスケールインジケータを追加する便利な方法はありますか?

matplotlibに便利な方法がありますか、3行(2つの小さな垂直、1つの水平)を描いてテキストを追加する必要がありますか?理想的な解決策では、データ次元に座標を設定する必要はありません。すなわち、私はちょうどhorizontalalignment='left', verticalalignment='bottom', transform=ax.transAxesの行に沿って何かを言い、データ座標の幅のみを指定します。

私はannotate()ととの戦いをしていましたが、私が結論づけるまで静かに彼らの文書は、彼らは正確に有用ではなかったが、私は間違っているかもしれません。

編集:

次のコードは、私がこれまでに来て、最も近いです。私はまだデータ座標系で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) 

Empty plot with scale indicator

+0

これが役に立つかもしれませんか? https://pypi.python。org/pypi/matplotlib-scalebar – DavidG

+0

これはそうですが、上記のプロットのスタイルと一致させる必要があります。それで正確にそのように見えます –

+0

水平な '' errorbar''と '' annotate''を使ってみましたか? – mommermi

答えて

2

プロットに水平スケールバー(またはスケールインジケータまたはスケールバー)を追加するコードです。バーの幅はデータ単位で与えられ、エッジの高さは軸単位の分数になります。

AnchoredOffsetboxに基づいており、これはVPackerを含んでいます。 VPackerは、その下の行にラベルを持ち、上の行にAuxTransformBoxというラベルを持っています。
AnchoredOffsetboxは、凡例の配置と同様のloc引数(例:loc=4は右下を示します)を使用して、軸を基準にして配置されています。しかし、AuxTransformBoxには、一連の要素が含まれています。これらの要素は、変換を使用してボックス内に配置されています。変換として、軸変換に従って軸座標と軸座標のデータ変換に従ってx座標を変換する混合変換を選択できます。これを行う変換は、実際には軸そのもののxaxis_transformです。この変換をAuxTransformBoxに指定すると、アーティストを指定することができます(この場合はLine2Dとなります)。バーの線はLine2D([0,size],[0,0])になります。

これらのすべては、既存のコードで使用するのが容易であるように、AnchoredOffsetboxをサブクラス化するクラスにパックすることができます。問題の希望通りの結果を達成するために

enter image description here

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) 

enter image description here

関連する問題