2013-05-22 65 views
11

私はquadmeshを使って単純な極座標プロットを作成しています。ここで私は何をしようとしている基本的に生成し、最小限のスクリプトがあります:matplotlibカラーバーの配置とサイズ

from __future__ import unicode_literals 
import numpy as np 
import matplotlib.pyplot as plt 

def make_plot(data,fig,subplot): 
    nphi,nt = data.shape 
    phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2. 
    theta_coords = np.linspace(0,np.radians(35),nt+1) 

    ax = fig.add_subplot(subplot,projection='polar') 
    ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6)) 
    ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0') 

    theta,phi = np.meshgrid(phi_coords,theta_coords) 
    quadmesh = ax.pcolormesh(theta,phi,data) 
    ax.grid(True) 
    fig.colorbar(quadmesh,ax=ax) 
    return fig,ax 


a = np.zeros((360,71)) + np.arange(360)[:,None] 
b = np.random.random((360,71)) 
fig = plt.figure() 
t1 = make_plot(a,fig,121) 
t2 = make_plot(b,fig,122) 
fig.savefig('test.png') 

上記のスクリプトは、次のようになりますプロットを作成します。

enter image description here

私はカラーバーをしたいと思います。

  1. 6ラベルと重複しません。
  2. は、プロットとほぼ同じ高さになるようにスケーリングしてください。

これを正しく行うにはどんなトリックがありますか? (このレイアウトは、私が使用する唯一のレイアウトではないことに注意してください。例えば、1x2レイアウト、または4x4レイアウトを使用するかもしれません...カラーバーを同じ高さにスケールする方法があるようです関連するプロット...)

答えて

12

あなたは、padの組み合わせでshrinkこれを行うことができ、かつaspect kwargsから:

from __future__ import unicode_literals 
import numpy as np 
import matplotlib.pyplot as plt 

def make_plot(data,fig,subplot): 
    nphi,nt = data.shape 
    phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2. 
    theta_coords = np.linspace(0,np.radians(35),nt+1) 

    ax = fig.add_subplot(subplot,projection='polar') 
    ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6)) 
    ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0') 

    theta,phi = np.meshgrid(phi_coords,theta_coords) 
    quadmesh = ax.pcolormesh(theta,phi,data) 
    ax.grid(True) 
    cb = fig.colorbar(quadmesh,ax=ax, shrink=.5, pad=.2, aspect=10) 
    return fig,ax,cb 


a = np.zeros((360,71)) + np.arange(360)[:,None] 
b = np.random.random((360,71)) 
fig = plt.figure() 
t1 = make_plot(a,fig,121) 
t2 = make_plot(b,fig,122) 

figure.colorbar doc

これらのパラメータのための最高値は側面に依存します軸の比。

軸のサイズは極座標プロットにシュリンクラップされないようです。したがって、1x2配列では、プロットの上下に、Axesオブジェクトの一部である空のスペースが多くあります。カラーバーのサイズは、ラウンドサイズではなく、長方形のサイズに基づいて設定されています。そのため、デフォルト値がうまく機能しないのはなぜですか。シュリンクラッピングを行う方法はおそらくありますが、その方法はわかりません。

別の方法は、右のアスペクト比の元であることをあなたの姿を強制することです:

サブプロットの広場を作る
fig.set_size_inches(10, 4) # for 1x2 
fig.set_size_inches(4, 10) # for 2x1 

、そのデフォルト値多かれ少なかれ仕事。

+0

これは2x1レイアウトでは機能しますが、1x2レイアウトでは機能しません(カラーバーが小さすぎる)。私は本当にレイアウトに依存しないソリューションを探しています。私のrcparamsが行く限り、私は確信していません。私は(私の知る限り)rcファイルを持っておらず、 'print matplotlib.rcParams ['bounding_box_tight']'は 'KeyError'になります。 – mgilson

+0

@mgilson私はキーが間違って記憶されている、編集を参照してください。私は根本的な問題は、 'axes'オブジェクトの境界ボックスが極座標プロットの周りを包むことがなく、すべてのカラーバーの長さがオーバーサイズの境界ボックスから離されているということです。 – tacaswell

+0

私はまだ 'savefig.bbox'の' KeyError'を取得します。私はさらに、isinstance(v、str)ならばmatplotlib.rcParams.values()のvに対してvを試してみました。空のリストを与えてくれました。私はバージョン1.1.1を使用しています。 – mgilson

15

この組み合わせ(およびこれに近い値)は、ディスプレイのサイズにかかわらず、カラーバーをプロットに合わせて維持するために「魔法のように」機能しているようです。

plt.colorbar(im,fraction=0.046, pad=0.04) 
+1

それは変な魔法です! –

+1

これは私にとって完璧に機能しました。 matplotlibの最新版を使用しています(執筆時点)。ありがとうございました! – user3125347

0

カラーバーの自動スケーリングはトリッキーであることが知られています。 this pageの最後に記載されている回避策を適用しようとすると、あなたの例やAxes3Dオブジェクトを使った試行ではうまくいきませんでした。 colorbarのコールシグネチャを見てみると、axキーワード引数は、「新しいカラーバー軸のスペースが盗まれるオブジェクト」です。これは、カラーバーが6と重なる理由を説明しています。したがって、デュアルAxesを維持する必要があります。悲しいことに、追加の軸を維持しなければならないことは、多くの手のハッキングを意味します。

#!/usr/bin/env python 
from __future__ import unicode_literals 
import numpy as np 
import matplotlib.pyplot as plt 

fig = plt.figure() 

N, M = 360, 71 
phi_coords = np.linspace(0, np.pi*2, M+1) -np.pi/2 
theta_coords = np.linspace(0, np.radians(35), N+1) 
theta, phi = np.meshgrid(phi_coords, theta_coords) 

# Original method 
a = np.zeros((N,M)) + np.arange(N)[:,None] 
ax1 = fig.add_subplot(1,2,1, projection="polar") 
ax1.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6)) 
ax1.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0') 
quadmesh = ax1.pcolormesh(theta, phi, a) 
fig.colorbar(quadmesh,ax=ax1) 

# Use ``add_axes`` to make a ``cax`` 
b = np.random.random((N,M)) 
ax2 = fig.add_subplot(1,2,2, projection="polar") 
ax2.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6)) 
ax2.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0') 
quadmesh = ax2.pcolormesh(theta, phi, b) 
# <hack> 
# Hack to force the drawing of the image. 
print(ax2.get_position()) 
import tempfile 
with tempfile.SpooledTemporaryFile() as fid: 
    fig.savefig(fid, format="png") 

# </hack> 
# Now the axes has been scaled to the final size. 
bbox = ax2.get_position() 
print(bbox) 
cax = fig.add_axes(
     [bbox.xmax*1.03, bbox.ymin, bbox.width*0.08, bbox.height] 
    ) 
fig.colorbar(quadmesh,cax=cax) 

fig.savefig('test.png') 

左側の画像は、オリジナルと同じですが、右側の画像は、極プロット、バーの高さからオフセットカラーバーが極座標に一致した:私は、次のよう一緒に石畳しました。ご覧のとおり、左手プロットの軸のサイズを取得するには、Figureを強制的に描画する必要がありました。再描画を強制しない場合、カラーバーのサイズは元の軸サイズに基づいており、左と同じサイズの軸を取得します。この時点で、Axesにカラーバーが自動的にメインAxesのサイズの変化を追跡するように指示する方法が見つかりませんでした。

関連する問題