首页 > 解决方案 > Positioning colorbar and second y-axis (matplotlib)

问题描述

I am trying to make a plot with a double y-axis and a colorbar next to it. However, the label of my second y-axis won't appear and I am having a bit of trouble positioning the colorbar right. My code can be found below:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm #colormap
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.axes_grid1 import make_axes_locatable
from matplotlib.transforms import Transform
from matplotlib.ticker import (
    AutoLocator, AutoMinorLocator)

x = np.linspace(-2.5, 2.5, 100)
y = np.linspace(-2.5, 2.5, 100)
xx, yy = np.meshgrid(x, y)

std_x = 1.
std_y = 1.
A = 10
Gaussian = A * np.exp(-(xx**2/(2*std_x**2) + yy**2/(2*std_y**2)))

fig = plt.figure()
ax = plt.subplot(111)
im = plt.imshow(Gaussian)
ax.set_xlabel("[m]")
ax.set_ylabel("[m]")
ax_new = ax.twinx().twiny()
ticks = np.linspace(0, 1, 5)
ticklabels = np.round(np.arctan(ticks*512/1e3)*3600) #hardcoded
plt.xticks(ticks, ticklabels)
plt.yticks(ticks, ticklabels)
ax_new.set_xlabel("arcsec")
ax_new.set_ylabel("arcsec")
ax_new.set_title("Atmosphere Structure", fontsize=20)
divider = make_axes_locatable(ax_new)
# on the figure total in percent [left, bottom, width, height]
cax = fig.add_axes([0.95, 0.1, 0.02, 0.75])
colorbar_1 = fig.colorbar(im, cax=cax)
colorbar_1.set_label('pwv in mm', labelpad=-10, y=1.05, rotation=0)
plt.show()

With a lot of finetuning, the plot now looks like this (I used a Gaussian for simplicity):

enter image description here

The colorbar is still slightly misaligned and the way I am positioning the colorbar now feels like a quick fix rather than a good solution. Does anyone know how to do this in a 'cleaner'/better way? And does someone know how to get the ylabel on the right to appear (ax_new.set_ylabel("arcsec"))?

I tried out the solution proposed in Plot multiple y-axis AND colorbar in matplotlib, but somehow it does not work for me.

Edit: When I replace cax = fig.add_axes([0.95, 0.1, 0.02, 0.75]) with cax = divider.append_axes("right", size="4%", pad="10%"), I get the following image:

enter image description here

Edit 2:

I have also tried using secondary_xaxis, which can be seen in the code below

def m2deg(x):
    arcsec = np.arctan(x*512/1e3)*180/np.pi
    return arcsec

def deg2m(x):
    m = np.tan(x/(512)*np.pi/180)*1e3
    return m

secax = ax.secondary_xaxis('top', functions=(m2deg, deg2m))
secax2 = ax.secondary_yaxis('right', functions=(m2deg, deg2m))
secax.set_label("degrees")
secax2.set_label("degrees")

It gives me the picture below: enter image description here

again, the axis labels don't show and the tickmarks do not have the right values (tan(0/(512)*pi/180)*1e3 = 0, and arctan(0*512/1e3)*180/pi = 0, so all 0's must be aligned).

标签: pythonmatplotlibplotaxis-labelscolorbar

解决方案


试试constrained_layout

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm #colormap

x = np.linspace(-2.5, 2.5, 100)
y = np.linspace(-2.5, 2.5, 100)
xx, yy = np.meshgrid(x, y)

std_x = 1.
std_y = 1.
A = 10
Gaussian = A * np.exp(-(xx**2/(2*std_x**2) + yy**2/(2*std_y**2)))

fig, ax = plt.subplots(constrained_layout=True)
im = ax.imshow(Gaussian)
ax_new = ax.twinx().twiny()
ticks = np.linspace(0, 1, 5)
ticklabels = np.round(np.arctan(ticks*512/1e3)*3600) #hardcoded
plt.xticks(ticks, ticklabels)
plt.yticks(ticks, ticklabels)
ax_new.set_xlabel("arcsec")
ax_new.set_ylabel("arcsec")
ax_new.set_title("Atmosphere Structure", fontsize=20)
colorbar_1 = fig.colorbar(im)
colorbar_1.set_label('pwv in mm', labelpad=-10, y=1.05, rotation=0)
plt.show()

在此处输入图像描述


推荐阅读