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):
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:
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:
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).