简体   繁体   中英

Using twiny() in an inset plot in Matplotlib

I'm trying to add a second x-axis to my inset plot that I created with InsetPosition from mpl_toolkits.axes_grid1.inset_locator (following eg https://scipython.com/blog/inset-plots-in-matplotlib/ ), but the second x-axis doesn't seem to show up and I can't figure out why.

This is the code I'm using:

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca()

from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
zoom_ax = fig.add_axes([0,0,1,1])
zoom_ax.set_axes_locator(InsetPosition(ax, [0.6, 0.6, 0.3, 0.3]))

def expansion(z):
    return 1.0 / (1.0 + z)

def redshift(a):
    return 1.0 / a - 1.0

def tick_function(a):
    return ["%.1f" % z for z in redshift(a)]

z_ticks = np.array([0.0, 0.5, 1.0, 2.0, 5.0, 100.0])
a_ticks = expansion(z_ticks)

twin_ax = zoom_ax.twiny()
twin_ax.set_xticks(a_ticks)
twin_ax.set_xticklabels(tick_function(a_ticks))
twin_ax.set_xlim(zoom_ax.get_xlim())

xmin, xmax = 0.0, 1.0
x = np.linspace(xmin, xmax)
zoom_ax.plot(x, np.sin(x))
zoom_ax.set_xlim(xmin, xmax)

plt.show()

This produces the following plot - without any twiny() axis:

以上代码的结果

Apparently twiny() has problems with the axes_locator used by zoom_ax (don't know if that is a bug or not). If you repeat the set_axes_locator() command for twin_ax , the resulting plot looks like what I would expect (I left out the axes ticks commands to make my example plot more comprehensible):

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca()

from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
zoom_ax = fig.add_axes([0,0,1,1])
zoom_ax.set_axes_locator(InsetPosition(ax, [0.6, 0.6, 0.3, 0.3]))

def expansion(z):
    return 1.0 / (1.0 + z)

def redshift(a):
    return 1.0 / a - 1.0

def tick_function(a):
    return ["%.1f" % z for z in redshift(a)]

z_ticks = np.array([0.0, 0.5, 1.0, 2.0, 5.0, 100.0])
a_ticks = expansion(z_ticks)

twin_ax = zoom_ax.twiny()
##twin_ax.set_xticks(a_ticks)
##twin_ax.set_xticklabels(tick_function(a_ticks))
twin_ax.set_xlim(zoom_ax.get_xlim())

xmin, xmax = 0.0, 1.0
x = np.linspace(xmin, xmax)
zoom_ax.plot(x, np.sin(x))
zoom_ax.set_xlim(xmin, xmax)

##the extra lines
twin_ax.set_axes_locator(InsetPosition(ax, [0.6, 0.6, 0.3, 0.3]))
x2 = np.linspace(xmin, 2*xmax)
twin_ax.plot(x2,np.cos(x2),'r')
twin_ax.set_xlim(xmin, 2*xmax)

plt.show()

This produces the following plot:

以上代码的结果

Maybe you want to use the usual mpl_toolkits.axes_grid1.inset_locator.inset_axes , which works fine even with twinning.

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca()

from mpl_toolkits.axes_grid1.inset_locator import inset_axes
zoom_ax = inset_axes(ax, "100%", "100%", bbox_to_anchor=[0.6, 0.6, 0.3, 0.3], 
                     bbox_transform=ax.transAxes)

def expansion(z):
    return 1.0 / (1.0 + z)

def redshift(a):
    return 1.0 / a - 1.0

def tick_function(a):
    return ["%.1f" % z for z in redshift(a)]

z_ticks = np.array([0.0, 0.5, 1.0, 2.0, 5.0, 100.0])
a_ticks = expansion(z_ticks)

twin_ax = zoom_ax.twiny()
twin_ax.set_xticks(a_ticks)
twin_ax.set_xticklabels(tick_function(a_ticks))
twin_ax.set_xlim(zoom_ax.get_xlim())

xmin, xmax = 0.0, 1.0
x = np.linspace(xmin, xmax)
zoom_ax.plot(x, np.sin(x))
zoom_ax.set_xlim(xmin, xmax)

plt.show()

From matplotlib 3.0 on you may simplify this even further, using Axes.inset_axes :

import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.gca()

zoom_ax = ax.inset_axes([0.6, 0.6, 0.3, 0.3])

def expansion(z):
    return 1.0 / (1.0 + z)

def redshift(a):
    return 1.0 / a - 1.0

def tick_function(a):
    return ["%.1f" % z for z in redshift(a)]

z_ticks = np.array([0.0, 0.5, 1.0, 2.0, 5.0, 100.0])
a_ticks = expansion(z_ticks)

twin_ax = zoom_ax.twiny()
twin_ax.set_xticks(a_ticks)
twin_ax.set_xticklabels(tick_function(a_ticks))
twin_ax.set_xlim(zoom_ax.get_xlim())

xmin, xmax = 0.0, 1.0
x = np.linspace(xmin, xmax)
zoom_ax.plot(x, np.sin(x))
zoom_ax.set_xlim(xmin, xmax)

plt.show()

The result is the same visually:

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM