matplotlib: how to get handles of existing twinx() axes?
Asked Answered
K

3

6

I want to create a figure with two y-axes and add multiple curves to each of those axes at different points in my code (from different functions).

In a first function, I create a figure:

   import matplotlib.pyplot as plt
   from numpy import *

   # Opens new figure with two axes
   def function1():
          f = plt.figure(1)
          ax1 = plt.subplot(211)
          ax2 = ax1.twinx()  

          x = linspace(0,2*pi,100)
          ax1.plot(x,sin(x),'b')
          ax2.plot(x,1000*cos(x),'g')

   # other stuff will be shown in subplot 212...

Now, in a second function I want to add a curve to each of the already created axes:

   def function2():
          # Get handles of figure, which is already open
          f = plt.figure(1)
          ax3 = plt.subplot(211).axes  # get handle to 1st axis
          ax4 = ax3.twinx()            # get handle to 2nd axis (wrong?)

          # Add new curves
          x = linspace(0,2*pi,100)
          ax3.plot(x,sin(2*x),'m')
          ax4.plot(x,1000*cos(2*x),'r')

Now my problem is that the green curve added in the first code block is not anymore visible after the second block is executed (all others are).

I think the reason for this is the line

    ax4 = ax3.twinx()

in my second code block. It probably creates a new twinx() instead of returning a handle to the existing one.

How would I correctly get the handles to already existing twinx-axes in a plot?

Kinslow answered 8/3, 2017 at 14:53 Comment(1)
Why not store the axes created in the first function and use them in the second, instead of trying to rederive them from the figure?Commonable
T
0

I would guess that the cleanest way would be to create the axes outside the functions. Then you can supply whatever axes you like to the function.

import matplotlib.pyplot as plt
import numpy as np

def function1(ax1, ax2):
    x = np.linspace(0,2*np.pi,100)
    ax1.plot(x,np.sin(x),'b')
    ax2.plot(x,1000*np.cos(x),'g')

def function2(ax1, ax2):
    x = np.linspace(0,2*np.pi,100)
    ax1.plot(x,np.sin(2*x),'m')
    ax2.plot(x,1000*np.cos(2*x),'r')

fig, (ax, bx) = plt.subplots(nrows=2)
axtwin = ax.twinx()

function1(ax, axtwin)
function2(ax, axtwin)

plt.show()
Tifanie answered 8/3, 2017 at 15:20 Comment(0)
C
6

you can use get_shared_x_axes (get_shared_y_axes) to get a handle to the axes created by twinx (twiny):

# creat some axes
f,a = plt.subplots()

# create axes that share their x-axes
atwin = a.twinx()

# in case you don't have access to atwin anymore you can get a handle to it with
atwin_alt = a.get_shared_x_axes().get_siblings(a)[0]

atwin == atwin_alt # should be True
Cyndycynera answered 31/10, 2019 at 18:36 Comment(1)
If sharex has been applied explicitly, as is often the case when dealing with multiple subplots, this will return additional Axes.Healthy
T
0

I would guess that the cleanest way would be to create the axes outside the functions. Then you can supply whatever axes you like to the function.

import matplotlib.pyplot as plt
import numpy as np

def function1(ax1, ax2):
    x = np.linspace(0,2*np.pi,100)
    ax1.plot(x,np.sin(x),'b')
    ax2.plot(x,1000*np.cos(x),'g')

def function2(ax1, ax2):
    x = np.linspace(0,2*np.pi,100)
    ax1.plot(x,np.sin(2*x),'m')
    ax2.plot(x,1000*np.cos(2*x),'r')

fig, (ax, bx) = plt.subplots(nrows=2)
axtwin = ax.twinx()

function1(ax, axtwin)
function2(ax, axtwin)

plt.show()
Tifanie answered 8/3, 2017 at 15:20 Comment(0)
H
0

I came up with a solution for my slightly different case. My plotting code is wrapped into a function. A minimal example of such a function would be:

def myplot(ax, data):
    ax.plot(data['left'], color='C0')
    ax.twinx().plot(data['right'], color='C1')

myplot(ax, {'left': [0, 1, 2, 3], 'right': [3, 2, 1, 0]})

Here's a modified version that stores a reference the second y-axis:

def myplot_persistent(ax, data):
    if 'twinx' in ax.__dict__.keys():
        ax_right = ax.__dict__['twinx']
    else:
        ax_right = ax.twinx()
        ax.__dict__['twinx'] = ax_right

    ax.plot(data['left'], color='C0')
    ax_right.plot(data['right'], color='C1')

(_, ax) = plt.subplots(1, 1)
myplot_persistent(ax, {'left': [0, 1, 2, 3], 'right': [3, 2, 1, 0]})
myplot_persistent(ax, {'left': [1, 2, 3], 'right': [2, 1, 0]})
Healthy answered 6/8, 2024 at 0:23 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.