How can I position the colorbar better? - python

I'm trying to align the right edge of both plots and have the colorbar hanging to the right. This is what I have:
import numpy as np
import matplotlib.pyplot as plt
def F(x, y):
u = x
v = y
return u, v
fig = plt.figure(figsize=(8, 8), tight_layout=True)
ax1 = plt.subplot(2, 1, 1)
ax2 = plt.subplot(2, 1, 2)
x, y = np.meshgrid(np.linspace(-1, 1, 10), np.linspace(-1, 1, 10))
u, v = F(x, y)
vres = np.sqrt(u ** 2 + v ** 2)
vector_field = ax1.quiver(x, y, u, v, vres)
fig.colorbar(vector_field, ax=ax1)
plt.show()
And this is what I got:
I've read the colorbar doc but couldn't find what I wanted, can anyone help?
Thanks in advance!

Updated solution:
You can actually just add another colorbar to your second subplot and make it not visible, like this.
fig.colorbar(vector_field, ax=ax2).ax.set_visible(False)
Complete code:
import numpy as np
import matplotlib.pyplot as plt
def F(x, y):
u = x
v = y
return u, v
fig = plt.figure(figsize=(8, 8), tight_layout=True)
ax1 = plt.subplot(2, 1, 1)
ax2 = plt.subplot(2, 1, 2)
x, y = np.meshgrid(np.linspace(-1, 1, 10), np.linspace(-1, 1, 10))
u, v = F(x, y)
vres = np.sqrt(u ** 2 + v ** 2)
vector_field = ax1.quiver(x, y, u, v, vres)
fig.colorbar(vector_field, ax=ax1)
fig.colorbar(vector_field, ax=ax2).ax.set_visible(False)
plt.show()
Old solution with different result:
I did not expext this to work, but is this what you need?
ax from colorbar can actually take a list of axes , not only one: fig.colorbar(vector_field, ax=[ax1, ax2]). You will also have to remove the tight_layout though...tight_layout=False
import numpy as np
import matplotlib.pyplot as plt
def F(x, y):
u = x
v = y
return u, v
fig = plt.figure(figsize=(8, 8), tight_layout=False)
ax1 = plt.subplot(2, 1, 1)
ax2 = plt.subplot(2, 1, 2)
x, y = np.meshgrid(np.linspace(-1, 1, 10), np.linspace(-1, 1, 10))
u, v = F(x, y)
vres = np.sqrt(u ** 2 + v ** 2)
vector_field = ax1.quiver(x, y, u, v, vres)
fig.colorbar(vector_field, ax=[ax1, ax2])
plt.show()

Related

Matplotlib:Why "set_yscale" rasise warning:RuntimeWarning: invalid value encountered in power ...?

This is the official code for Matplotlib:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import NullFormatter, FixedLocator
# Fixing random state for reproducibility
np.random.seed(19680801)
# make up some data in the interval ]0, 1[
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))
# plot with various axes scales
fig, axs = plt.subplots(3, 2, figsize=(6, 8),
constrained_layout=True)
# linear
ax = axs[0, 0]
ax.plot(x, y)
ax.set_yscale('linear')
ax.set_title('linear')
ax.grid(True)
# log
ax = axs[0, 1]
ax.plot(x, y)
ax.set_yscale('log')
ax.set_title('log')
ax.grid(True)
# symmetric log
ax = axs[1, 1]
ax.plot(x, y - y.mean())
ax.set_yscale('symlog', linthresh=0.02)
ax.set_title('symlog')
ax.grid(True)
# logit
ax = axs[1, 0]
ax.plot(x, y)
ax.set_yscale('logit')
ax.set_title('logit')
ax.grid(True)
# Function x**(1/2)
def forward(x):
return x**(1/2)
def inverse(x):
return x**2
ax = axs[2, 0]
ax.plot(x, y)
ax.set_yscale('function', functions=(forward, inverse))
ax.set_title('function: $x^{1/2}$')
ax.grid(True)
ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 1, 0.2)**2))
ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 1, 0.2)))
# Function Mercator transform
def forward(a):
a = np.deg2rad(a)
return np.rad2deg(np.log(np.abs(np.tan(a) + 1.0 / np.cos(a))))
def inverse(a):
a = np.deg2rad(a)
return np.rad2deg(np.arctan(np.sinh(a)))
ax = axs[2, 1]
t = np.arange(0, 170.0, 0.1)
s = t / 2.
ax.plot(t, s, '-', lw=2)
ax.set_yscale('function', functions=(forward, inverse))
ax.set_title('function: Mercator')
ax.grid(True)
ax.set_xlim([0, 180])
ax.yaxis.set_minor_formatter(NullFormatter())
ax.yaxis.set_major_locator(FixedLocator(np.arange(0, 90, 10)))
plt.show()
We focus on the 'function: x^(1/2)' picture
What I need is to reverse the axis scale.
Here is my code:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import NullFormatter, FixedLocator
# Fixing random state for reproducibility
np.random.seed(19680801)
# make up some data in the interval ]0, 1[
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(1,len(y)+1)
#x=np.array(x,dtype=np.complex)
# plot with various axes scales
fig, axs = plt.subplots(1, 1, figsize=(6, 8),
constrained_layout=True)
# Function x**(1/2)
def forward(x):
return x**(1/3)
def inverse(x):
return x**3
ax = axs
ax.plot(x, y)
ax.set_yscale('function', functions=(inverse,forward)) #I reverse the order.
ax.set_title('function: $x^{1/3}$')
ax.grid(True)
plt.show()
But the results were not satisfactory
And it triggered a warning:
RuntimeWarning: invalid value encountered in power
return x**(1/3)
I don't know what went wrong.I want the bigger the Y-axis, the bigger the spacing.Please help me!Thanks.

Adding contour labels doesn't label each contour, and removes some of the contour lines [duplicate]

The sample data is generated as follows,
import matplotlib as mpl
print(mpl.__version__) # 3.3.3
import matplotlib.pyplot as plt
import numpy as np
def f(x, y=0):
return np.piecewise(x, [x < 1, np.logical_and(1 <= x, x < 10), x >= 10], [lambda x: 0, lambda x: (x - 1) / 9 * 1000, lambda x: 1000])
x = np.logspace(-5, 5, 100)
y = np.logspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
I try to plot using the following code, but some contours disappear after calling clabel.
fig, ax = plt.subplots(figsize=(5, 3), dpi=120)
cr = ax.contour(X, Y, Z, levels=3, colors='black')
ax.clabel(cr, inline=True, fontsize=8, fmt='%d')
ax.set_xscale('log')
ax.set_yscale('log')
plt.show()
This issue still appears even when contour linewidth and label font size are decreased.
fig, ax = plt.subplots(figsize=(5, 3), dpi=120)
cr = ax.contour(X, Y, Z, levels=3, colors='black', linewidths=0.6)
ax.clabel(cr, inline=True, fontsize=3, fmt='%d')
ax.set_xscale('log')
ax.set_yscale('log')
plt.show()
I cannot figure out how to fix the weird behaviours of contour and clabel, and I suspect it is due to their incompatibility with log scale.
It is indeed a problem of the log axes, especially around the asymptote zero. However, why not defining the log axes before plotting, so matplotlib can take this into consideration when plotting?
import matplotlib as mpl
print(mpl.__version__) # 3.3.3
import matplotlib.pyplot as plt
import numpy as np
def f(x, y=0):
return np.piecewise(x, [x < 1, np.logical_and(1 <= x, x < 10), x >= 10], [lambda x: 0, lambda x: (x - 1) / 9 * 1000, lambda x: 1000])
x = np.logspace(-5, 5, 100)
y = np.logspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots(figsize=(5, 3), dpi=120)
ax.set_xscale('log')
ax.set_yscale('log')
cr = ax.contour(X, Y, Z, levels=3, colors='black')
ax.clabel(cr, inline=True, fontsize=8, fmt='%d')
plt.show()
Sample output:

Why do matplotlib contour labels make contours disappear?

The sample data is generated as follows,
import matplotlib as mpl
print(mpl.__version__) # 3.3.3
import matplotlib.pyplot as plt
import numpy as np
def f(x, y=0):
return np.piecewise(x, [x < 1, np.logical_and(1 <= x, x < 10), x >= 10], [lambda x: 0, lambda x: (x - 1) / 9 * 1000, lambda x: 1000])
x = np.logspace(-5, 5, 100)
y = np.logspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
I try to plot using the following code, but some contours disappear after calling clabel.
fig, ax = plt.subplots(figsize=(5, 3), dpi=120)
cr = ax.contour(X, Y, Z, levels=3, colors='black')
ax.clabel(cr, inline=True, fontsize=8, fmt='%d')
ax.set_xscale('log')
ax.set_yscale('log')
plt.show()
This issue still appears even when contour linewidth and label font size are decreased.
fig, ax = plt.subplots(figsize=(5, 3), dpi=120)
cr = ax.contour(X, Y, Z, levels=3, colors='black', linewidths=0.6)
ax.clabel(cr, inline=True, fontsize=3, fmt='%d')
ax.set_xscale('log')
ax.set_yscale('log')
plt.show()
I cannot figure out how to fix the weird behaviours of contour and clabel, and I suspect it is due to their incompatibility with log scale.
It is indeed a problem of the log axes, especially around the asymptote zero. However, why not defining the log axes before plotting, so matplotlib can take this into consideration when plotting?
import matplotlib as mpl
print(mpl.__version__) # 3.3.3
import matplotlib.pyplot as plt
import numpy as np
def f(x, y=0):
return np.piecewise(x, [x < 1, np.logical_and(1 <= x, x < 10), x >= 10], [lambda x: 0, lambda x: (x - 1) / 9 * 1000, lambda x: 1000])
x = np.logspace(-5, 5, 100)
y = np.logspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = f(X, Y)
fig, ax = plt.subplots(figsize=(5, 3), dpi=120)
ax.set_xscale('log')
ax.set_yscale('log')
cr = ax.contour(X, Y, Z, levels=3, colors='black')
ax.clabel(cr, inline=True, fontsize=8, fmt='%d')
plt.show()
Sample output:

Matplotlib 3d: surface does not cover a line

I draw a plane and a line crossing the plane.
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
def plot_x_axis(ax):
x = np.array([-1, 1])
y = np.array([0, 0])
z = np.array([0, 0])
ax.plot(x, y, z, color='green')
def plot_yz_plane(ax):
a = np.array([0, 1, 0])
b = np.array([0, 0, 1])
U, V = np.meshgrid(np.linspace(-0.5, 0.5, 3), np.linspace(-0.5, 0.5, 3))
x = a[0] * U + b[0] * V
y = a[1] * U + b[1] * V
z = a[2] * U + b[2] * V
surf = ax.plot_surface(x, y, z, rstride=1, cstride=1, alpha=1.0, color='red')
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plot_x_axis(ax)
plot_yz_plane(ax)
plt.show()
I expect that a part of this line (placed behind the plane) will be covered by the plane, but actually matplotlib shows all the objects as if the plane is transparent. How to fix this problem?

matplotlib: add circle to plot

How do I add a small filled circle or point to a countour plot in matplotlib?
Here is an example, using pylab.Circle:
import numpy as np
import matplotlib.pyplot as plt
e = np.e
X, Y = np.meshgrid(np.linspace(0, 5, 100), np.linspace(0, 5, 100))
F = X ** Y
G = Y ** X
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
circ = plt.Circle((e, e), radius=0.07, color='g')
plt.contour(X, Y, (F - G), [0])
ax.add_patch(circ)
plt.show()
And here is another example (though not a contour plot) from the docs.
Or, you could just use plot:
import numpy as np
import matplotlib.pyplot as plt
e = np.e
X, Y = np.meshgrid(np.linspace(0, 5, 100), np.linspace(0, 5, 100))
F = X ** Y
G = Y ** X
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
plt.contour(X, Y, (F - G), [0])
plt.plot([e], [e], 'g.', markersize=20.0)
plt.show()

Categories

Resources