2016-09-25 27 views
1

プライマリとセカンダリの両方の共有を有効にしようとしています。サンプルプロットは以下のコードで示されています。プロットには2つの水平軸が含まれ、プライマリ軸のグリッドは緑色で表示され、もう1つの軸は赤色のグリッドが表示されます。Pythonでセカンダリ軸(twiny)の共有を有効にする方法

#!/usr/bin/python 

# -*- coding: utf-8 -*- 

import numpy as np 
import matplotlib.pyplot as plt 

FIRST = 0.0 
LAST = 2.0 
STEP = 0.01 

t = np.arange(FIRST, LAST, STEP) 

s1 = np.sin(2*np.pi*t) 
s2 = np.exp(-t) 
s3 = s1*s2 

############################################################################### 

plt.rc('axes', grid=True) 
plt.rc('grid', color='0.75', linestyle='-', linewidth=0.5) 

fig3 = plt.figure() 
ax1primary = plt.subplot2grid((4,3), (0,0), colspan=3, rowspan=2) 
ax2primary = plt.subplot2grid((4,3), (2,0), colspan=3, sharex=ax1primary) 
ax3primary = plt.subplot2grid((4,3), (3,0), colspan=3, sharex=ax1primary) 

ax1primary.plot(t,s1) 
ax1primary.set_yticks(np.arange(-0.9, 1.0, 0.3)) 
ax1primary.xaxis.grid(color='green') 

ax2primary.plot(t[:150],s2[:150]) 
ax2primary.set_yticks(np.arange(0.3, 1, 0.2)) 
ax2primary.xaxis.grid(color='green') 

ax3primary.plot(t[30:],s3[30:]) 
ax3primary.plot([0,2],[0.2,0.2],'m') 
ax3primary.set_yticks(np.arange(-0.4, 0.7, 0.2)) 
ax3primary.xaxis.grid(color='green') 

INDEX = t[np.where(abs(s3-0.2) < 0.005)[0]] 
INDEX = np.append(INDEX, LAST) 
INDEX = np.insert(INDEX, 0, FIRST) 

ax1secondary = ax1primary.twiny() 
ax1secondary.set_xticks(INDEX) 
ax1secondary.xaxis.grid(color='red') 

ax2secondary = ax2primary.twiny() 
ax2secondary.set_xticks(INDEX) 
ax2secondary.xaxis.grid(color='red') 

ax3secondary = ax3primary.twiny() 
ax3secondary.set_xticks(INDEX) 
ax3secondary.xaxis.grid(color='red') 

plt.tight_layout() 
plt.subplots_adjust(hspace=0) 

for ax in [ax1primary, ax2primary, ax2secondary, ax3secondary]: 
    plt.setp(ax.get_xticklabels(), visible=False) 

############################################################################### 

plt.show() 

静的な数字には問題はありません。 サブプロットの1つをパン(またはズーム)し始めると、問題は明らかになります。プライマリ(緑色)軸は完全に同期しており、すべてのサブプロット内を移動しますが、セカンダリ(赤色)軸は不整列になり、アクティブなサブプロット内でのみ移動します。

これを修正する方法はありますか?


私が達成したい動作は以下の通りです:

Iは、図の下部にダニや他の一般的に(すべての3つのサブプロットのための)一つの共通の「プライマリ」、x軸を必要とします」二次的な "x軸(すべての3つのサブプロットに対して)が図の上にあるティックを付けて表示されます。プライマリ軸は標準的な間隔の軸ですが、セカンダリ軸はカスタマイズされたティック(例えばゼロクロス)を示しますこれは上記の例ですべて満たされています。今度は、サブプロットのパンやズームをしながらも満足する必要があります。

+0

あなたが探している動作がわかりません。 'twiny'は、共有されたy軸を持つ独立したx軸を作成するので、' ay1c'、 'ay2c'と' ay3c'のサブプロットの中でパンすると、x軸は親軸と "同期しない" 。一方、あなたの 'ax1c'、' ax2c'と 'ax3c'サブプロットはx軸は共通ですが、独立したy軸を使って作成されました。すべてのプロットがx軸とy軸の両方を共有しますか? –

+0

私はそれが混乱していることを理解することができます。私は軸名の良い選択をしなかった。 'ay1c'、' ay2c'、および 'ay3c'はy軸とは何の関係もありません(混乱を避けるために上のサンプルコードで軸名を変更します。この洞察に感謝します)。それにもかかわらず、達成したい動作は、図の下部にティックが付いた共通のx軸(3つのサブプロットすべて)と、上部にティックがある別の共通のx軸(3つのサブプロットすべて)です図の –

+0

これは 'twinx'ではなく' twinx'を使って 'ay1c'などを作成したいと思うようです。' twiny'は共通のy軸と独立したx軸を与​​えますが、共通のx軸独立したy軸を含む。 –

答えて

0

は、残念ながら、提案されたコールバック・ソリューションは、十分に堅牢ではありません。ほとんどの場合パンがうまく動作しますが、ズーミングは災害です。しかし、あまりにもしばしばグリッドが整列しない。

コールバックソリューションを改善する方法がわかるまでは、カスタムグリッドをコーディングしてプロット内の値に注釈を付けることにしました。

#!/usr/bin/python 

# -*- coding: utf-8 -*- 

import numpy as np 
import matplotlib.pyplot as plt 

FIRST = 0.0 
LAST = 2.0 
STEP = 0.01 

t = np.arange(FIRST, LAST, STEP) 

s1 = np.sin(2*np.pi*t) 
s2 = np.exp(-t) 
s3 = s1*s2 

############################################################################### 

plt.rc('axes', grid=True) 
plt.rc('grid', color='0.75', linestyle='-', linewidth=0.5) 

fig3 = plt.figure() 
ax1primary = plt.subplot2grid((4,3), (0,0), colspan=3, rowspan=2) 
ax2primary = plt.subplot2grid((4,3), (2,0), colspan=3, sharex=ax1primary) 
ax3primary = plt.subplot2grid((4,3), (3,0), colspan=3, sharex=ax1primary) 

ax1primary.plot(t,s1) 
ax1primary.set_yticks(np.arange(-0.9, 1.0, 0.3)) 
ax1primary.xaxis.grid(color='green') 
ax1primary.set_ylim(-1, 1) 

ax2primary.plot(t[:150],s2[:150]) 
ax2primary.set_yticks(np.arange(0.3, 1, 0.2)) 
ax2primary.xaxis.grid(color='green') 
ax2primary.set_ylim(0.2, 1) 

ax3primary.plot(t[30:],s3[30:]) 
ax3primary.plot([0,2],[0.2,0.2],'m') 
ax3primary.set_yticks(np.arange(-0.4, 0.7, 0.2)) 
ax3primary.xaxis.grid(color='green') 
ax3primary.set_ylim(-0.6, 0.8) 

INDEX = np.where(abs(s3-0.2) < 0.005)[0] 

for i in range(0, len(INDEX)): 
    ax1primary.annotate(t[INDEX[i]], xy=(t[INDEX[i]], 0)) 

ax1primary.plot([t[INDEX], t[INDEX]], [-1e9 * np.ones(len(INDEX)), 1e9 * np.ones(len(INDEX))], 'r') 
ax2primary.plot([t[INDEX], t[INDEX]], [-1e9 * np.ones(len(INDEX)), 1e9 * np.ones(len(INDEX))], 'r') 
ax3primary.plot([t[INDEX], t[INDEX]], [-1e9 * np.ones(len(INDEX)), 1e9 * np.ones(len(INDEX))], 'r') 

plt.tight_layout() 
plt.subplots_adjust(hspace=0) 

for ax in [ax1primary, ax2primary]: 
    plt.setp(ax.get_xticklabels(), visible=False) 

############################################################################### 

plt.show() 
1

ご質問ありがとうございます。 twinyの用途は、独自のスケールとオフセットを持つ2番目の完全に独立したx軸を作成してプロットすることです。しかし、あなたのケースでは、twinyによって作成されたセカンダリx軸を、カスタムxティックの2番目のセットを表示する方法としてのみ使用しています。この軸は常に親X軸と同じスケールとオフセットを持ちます。

一つのアプローチは、主軸がパンしますいつでも二軸の限界を更新callbackを作成するには、次のようになります。

from matplotlib.backend_bases import NavigationToolbar2 

parents = [ax1primary, ax2primary, ax3primary] 
children = [ax1secondary, ax2secondary, ax3secondary] 

def callback(event=None): 
    # return immediately if the figure toolbar is not in "navigation mode" 
    if not isinstance(parents[0].figure.canvas.manager.toolbar, 
         NavigationToolbar2): 
     return 
    for parent, child in zip(parents, children): 
     child.set_xlim(*parent.get_xlim()) 
     child.set_ylim(*parent.get_ylim()) 

# connect the callback to the figure canvas 
fig3.canvas.mpl_connect('motion_notify_event', callback) 
+0

これは有望な解決策のようです。実際、私は単純なもの、例えば 'ax2secondary = ax2primary.twiny(sharex = ax1secondary)'のようなものを望んでいました。 –

関連する問題