I am trying to plot x vs y data and trying to see the variation of x and y with respect to z using a colorbar.
x = [1,2,3,4,5]
x_err = [0.1,0.2,0.3,0.4,0.5]
y = [5,6,7,8,9]
y_err = [0.5,0.6,0.7,0.8,0.9]
z = [3,4,5,6,7]
fig, ax = plt.subplots()
ax.errorbar(x, y, x_err, y_err, fmt='*', elinewidth = 0.9, ecolor='black')
scatter = ax.scatter(x, y, c=z, s=5)
cbar = fig.colorbar(scatter,cmap='viridis')
cbar.set_label('z')
I need the errorbar to have the same color as that of the datapoint.
You could compute the ecolor from the same cmap. Not sure there aren't any solution to do that for you, but it doesn't cost much
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
x = [1,2,3,4,5]
x_err = [0.1,0.2,0.3,0.4,0.5]
y = [5,6,7,8,9]
y_err = [0.5,0.6,0.7,0.8,0.9]
z = [3,4,5,6,7]
fig, ax = plt.subplots()
# Rest of your code is yours. Only this line is added (and next line modified to use this "col" as ecolor
col=cm.viridis((np.array(z)-min(z))/(max(z)-min(z))) # RGBA colors from z
ax.errorbar(x, y, x_err, y_err, ecolor=col, fmt='*', elinewidth = 0.9)
scatter = ax.scatter(x, y, c=z, s=5)
cbar = fig.colorbar(scatter,cmap='viridis')
cbar.set_label('z')
plt.show()
Result
Related
Let's see a contrived example of 2 matplotlib.pyplot functions returning a plot, which then may be accessed through plt.gcf() or plt.gca() methods:
x = np.linspace(-5, 5, 11)
y = x
y_2 = x * x
plt.plot(x,y)
fig_1 = plt.gcf()
ax_1 = plt.gca()
#plt.close()
plt.plot(x,y_2)
fig_2 = plt.gcf()
ax_2 = plt.gca()
#plt.close()
How would I nicely draw fig_1 and fig_2 objects alongside through e.g. plt.subplots(1,2) (given x, y, y_2 are not accessable)
Use the add_subplot method of the Figure object to draw the two plots alongside.
Try this:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 11)
y = x
y_2 = x * x
fig, axs = plt.subplots(1, 2) # create a figure with subplots
axs[0].plot(x, y) # first figure
axs[1].plot(x, y_2) # second figure
plt.show()
if no given given x, y, y_2:
fig, axs = plt.subplots(1, 2)
axs[0].plot(x, y)
axs[1].plot(x, y_2)
plt.show()
I want to plot a curve over a background image with the x and y axis in logscale. However, when I try to do so, the image is stretched by the logscale. I obtain this figure
This is the code I wrote.
import numpy as np
import matplotlib.pyplot as plt
x = np.random.uniform(low=0, high=10**6, size=(100,))
y = np.random.uniform(low=10**(-14), high=10**(-10), size=(100,))
x.sort()
y.sort()
xm = len(x)
ym = len(y)
img = plt.imread("quiverplot.png")
fig, ax2 = plt.subplots()
plt.plot(x, y)
ax2.set_xscale('log')
ax2.set_yscale('log')
ax1 = ax2.twinx()
img = ax1.imshow(img, zorder=0, extent=[x[0], x[xm-1], y[0], y[ym-1]], aspect='auto')
fig.tight_layout()
plt.show()
Thanks for any advices you can give me.
Don't use twinx(), but create a new axes with matplotlib.pyplot.axes().
You can do like this controlling the frame(background), x/y axis, and z-order.
fig, ax2 = plt.subplots()
ax2.plot(x, y)
ax2.set_xscale('log')
ax2.set_yscale('log')
ax2.set_frame_on(False)
ax2.zorder = 1
ax1 = plt.axes(ax2.get_position(True))
ax1.set_frame_on(False)
ax1.set_axis_off()
ax1.imshow(img, extent=[x[0], x[xm-1], y[0], y[ym-1]], aspect='auto')
...
It will be simpler if you change the order of plotting like this.
fig, ax2 = plt.subplots()
ax2.imshow(img, extent=[x[0], x[xm-1], y[0], y[ym-1]], aspect='auto')
ax2.set_axis_off()
ax1 = plt.axes(ax2.get_position(True))
ax1.set_frame_on(False)
ax1.set_xscale('log')
ax1.set_yscale('log')
ax1.plot(x, y)
...
My code is the following and I believe should produce a chart where a scatter plot is superimposed on a contourf plot (i.e. appears on the foreground)
But that does not happen.
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.scatter(examples[:,0], examples[:, 1])
ax.contourf(x, y, Z)
I expected that the scatter plot below would be superimposed on the contourf plot:
plt.scatter(x = examples[:,0], y = examples[:, 1])
Why is this and how the code should be changed?
Just swap contourf and scatter order:
import numpy as np
import matplotlib.pyplot as plt
N = 1000
xl = np.linspace(0, 10, N)
yl = np.linspace(0, 10, N)
x, y = np.meshgrid(xl, yl)
Z = x**2 + y**2
examples = np.random.uniform(low = 0, high = 10, size = (10, 2))
fig, ax = plt.subplots()
ax.contourf(x, y, Z)
ax.scatter(examples[:,0], examples[:, 1], color = 'red')
plt.show()
The last plot line you write overlaps the previous one.
I want to plot a surface and zoom to a specific part of it.
I have:
r1 = np.arange(10)
r2 = np.arange(15)
x, y = np.meshgrid(r2,r1)
z = np.random.rand(10,15)
fig = plt.figure(figsize=(16,10))
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, cmap=cm.jet)
axes = plt.gca()
fig.tight_layout()
plt.show()
That gives:
Now, if I set axis limits, I have a problem
r1 = np.arange(10)
r2 = np.arange(15)
x, y = np.meshgrid(r2,r1)
z = np.random.rand(10,15)
fig = plt.figure(figsize=(16,10))
ax = fig.gca(projection='3d')
surf = ax.plot_surface(x, y, z, cmap=cm.jet)
axes = plt.gca()
axes.set_xlim([r1[2],r1[8]])
axes.set_ylim([r2[2],r2[8]])
fig.tight_layout()
plt.show()
gives:
What I was expecting was it to cut the original fig in the limits I asked, without putting the plot outside the box. How do I do that?
I am trying to plot a figure in Python with two 3D graphs (same function, different angles) and a 2D contour map of the same function and I'm not sure why but the two first figures are okay and the contour map is weird, it appears at the bottom of the two first figures and the sizing is all weird (see the picture attached). Is there a way to place the map at the right of the 2 other figures and to resize it to make it more like a square?
Thank you for your help.
Here's my code :
import numpy as np
import matplotlib.pylab as plt
import matplotlib.cm as cm
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-5, 5, 0.01)
y = np.arange(-5, 5, 0.01)
X, Y = np.meshgrid(x, y)
Z = 5 + (10 * X**2 + 20 * Y**2) * np.exp((-X**2)-(Y**2)) + 3 *np.sin(X) - np.sin(Y)
fig = plt.figure(figsize=(15,5))
ax1 = plt.subplot(131, projection='3d')
surf1 = ax1.plot_surface(X, Y, Z, cmap=cm.coolwarm)
ax2 = plt.subplot(132, projection='3d')
surf2 = ax2.plot_surface(X, Y, Z, cmap=cm.coolwarm)
for angle in range(0,360):
ax2.view_init(20, angle)
plt.pause(.001)
ax3 = plt.subplot(133)
surf3 = ax3.contour(X, Y, Z, colors='black', linestyles='dashed')
plt.clabel(surf3, fmt = '%.0f', inline=True, fontsize=8)
ax1.set_xlabel('X')
ax2.set_xlabel('X')
ax3.set_xlabel('X')
ax1.set_ylabel('Y')
ax2.set_ylabel('Y')
ax3.set_ylabel('Y')
ax1.set_zlabel('Z')
ax2.set_zlabel('Z')
plt.show()
Got it:
import numpy as np
import matplotlib.pylab as plt
import matplotlib.cm as cm
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-5, 5, 0.01)
y = np.arange(-5, 5, 0.01)
X, Y = np.meshgrid(x, y)
Z = 5 + (10 * X**2 + 20 * Y**2) * np.exp((-X**2)-(Y**2)) + 3 *np.sin(X) - np.sin(Y)
fig = plt.figure(figsize=(15,5))
ax1 = fig.add_subplot(1, 3, 1, projection='3d')
surf1 = ax1.plot_surface(X, Y, Z, cmap=cm.coolwarm)
ax3 = fig.add_subplot(1, 3, 2)
surf3 = ax3.contour(X, Y, Z, colors='black', linestyles='dashed')
plt.clabel(surf3, fmt = '%.0f', inline=True, fontsize=8)
ax2 = fig.add_subplot(1, 3, 3, projection='3d')
surf2 = ax2.plot_surface(X, Y, Z, cmap=cm.coolwarm)
for angle in range(0,360):
ax2.view_init(20, angle)
plt.pause(.001)
ax1.set_xlabel('X')
ax2.set_xlabel('X')
ax3.set_xlabel('X')
ax1.set_ylabel('Y')
ax2.set_ylabel('Y')
ax3.set_ylabel('Y')
ax1.set_zlabel('Z')
ax2.set_zlabel('Z')
plt.show()