matplotlib xticks labels overlap - matplotlib

I am not able to get nicer spaces between the xticks with the following code:
import random
import matplotlib.pyplot as plt
coverages = [random.randint(1,10)*2] * 100
contig_names = ['AAB0008r'] * len(coverages)
fig = plt.figure()
fig.clf()
ax = fig.add_subplot(111)
ax.yaxis.grid(True, linestyle='-', which='major', color='grey', alpha=0.5)
ind = range(len(coverages))
rects = ax.bar(ind, coverages, width=0.2, align='center', color='thistle')
ax.set_xticks(ind)
ax.set_xticklabels(contig_names)
#function to auto-rotate the x axis labels
fig.autofmt_xdate()
plt.show()
How to get more space between the xticks so they do not look like overlapped anymore?
Thank you in advance.

You can try changing the figure size, the size of the xticklabels, their angle of rotation, etc.
# Set the figure size
fig = plt.figure(1, [20, 8])
# Set the x-axis limit
ax.set_xlim(-1,100)
# Change of fontsize and angle of xticklabels
plt.setp(ax.get_xticklabels(), fontsize=10, rotation='vertical')

Related

Colorbar in plots with embedded plots

While I managed to put a plot inside a plot (see the question here), I am finding trouble putting a colorbar to the larger (outside) plot. The code below is as simple as it gets, but for some reason it places the colorbar in the wrong axis:
import numpy as np
from numpy import random
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
# Canvas
fig, ax1 = plt.subplots(figsize=(12, 10))
left, bottom, width, height = [0.65, 0.15, 0.32, 0.30]
ax2 = fig.add_axes([left, bottom, width, height])
# Labels
xlabel = 'x'
ylabel = 'y'
cbarlabel = 'Color'
cmap = plt.get_cmap('turbo')
# Data
x, y, z = np.random.rand(3,200)
# Plotting
sc = ax1.scatter(x, y, marker='o', c=z, cmap=cmap)
ax2.scatter(x, y, c=z, cmap=cmap)
#
ax1.set_xlabel(xlabel)
ax1.set_ylabel(ylabel)
ax1.legend(fontsize=12, loc='upper left')
plt.tight_layout()
# Colormap
ax1 = plt.gca()
divider = make_axes_locatable(plt.gca())
cax = divider.append_axes("right", "2%", pad="1%")
cbar = plt.colorbar(sc, cax=cax) # Colorbar
cbar.set_label(cbarlabel, rotation=270, labelpad=30)
sc.set_clim(vmin=min(z), vmax=max(z))
#
plt.show()
I have also tried inset_axes as in the documentation example, to no avail.
The trick is to actually set active axes with plt.sca(ax1) and then create colorbar. I also simplified a code little bit.
Here is modified code putting colormap to the large plot:
import matplotlib.pyplot as plt
import numpy as np
from numpy import random
# Canvas
fig, ax1 = plt.subplots(figsize=(12, 10))
left, bottom, width, height = [0.45, 0.15, 0.32, 0.30]
ax2 = fig.add_axes([left, bottom, width, height])
# Labels
xlabel = 'x'
ylabel = 'y'
cbarlabel = 'Color'
cmap = plt.get_cmap('turbo')
# Data
x, y, z = np.random.rand(3,200)
# Plotting
sc = ax1.scatter(x, y, marker='o', c=z, cmap=cmap)
ax2.scatter(x, y, c=z, cmap=cmap)
# Set active axes
plt.sca(ax1)
cbar = plt.colorbar(sc) # Colorbar
cbar.set_label(cbarlabel, rotation=270, labelpad=30)
sc.set_clim(vmin=min(z), vmax=max(z))
#
ax1.set_xlabel(xlabel)
ax1.set_ylabel(ylabel)
ax1.legend(fontsize=12, loc='upper left')
plt.tight_layout()
plt.show()
Resulting in:

How to remove offset of axis in matplotlib 3d plot?

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim([0, 1])
plt.show()
results in the following plot:
There is a small margin between the axis and there limits.
How can I get rid of this offset of the axis.
For example ax.set_xlim([0, 1]) has not effect!

Three plot in one figure using Matplotlib

I want my plot to look like the image below, how can I achieve that using Matplotlib?
And thanks
You can use GridSpec similar to this tutorial. Possibly there will be not enough space for the y tick labels, which can be mitigated by increasing the default wspace.
import matplotlib.pyplot as plt
fig, axs = plt.subplots(ncols=4, nrows=2, figsize=(12, 7), gridspec_kw={'wspace': 0.4})
gs = axs[0, 0].get_gridspec()
for ax in axs.ravel():
ax.remove()
ax1 = fig.add_subplot(gs[0, :2])
ax1.set_ylabel('A')
ax2 = fig.add_subplot(gs[0, 2:])
ax2.set_ylabel('B')
ax3 = fig.add_subplot(gs[1, 1:3])
ax3.set_ylabel('C')
for ax in (ax1, ax2, ax3):
ax.set_xlabel('D')
ax.legend(handles=[], title='legend', loc='upper right', frameon=False)
plt.show()

unexpected constant color using matplotlib surface_plot and facecolors

I am plotting a function on the surface of a sphere. To test my code, I simply plot the spherical coordinate phi divided by pi. I get
Unexpectedly, half of the sphere is of the same color, and the colors on the other half aren't correct (at phi=pi, i should get 1, not 2). If I divide the data array by 2, the problem disappears. Can someone explain to me what is happening?
Here is the code I use:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
# prepare the sphere surface
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
phi = np.linspace(0,2*np.pi, 50)
theta = np.linspace(0, np.pi, 25)
x=np.outer(np.cos(phi), np.sin(theta))
y=np.outer(np.sin(phi), np.sin(theta))
z=np.outer(np.ones(np.size(phi)), np.cos(theta))
# prepare function to plot
PHI=np.outer(phi,np.ones(np.size(theta)))
THETA=np.outer(np.ones(np.size(phi)),theta)
data = PHI/np.pi
# plot
surface=ax.plot_surface(x, y, z, cstride=1, rstride=1,
facecolors=cm.jet(data),cmap=plt.get_cmap('jet'))
# add colorbar
m = cm.ScalarMappable(cmap=surface.cmap,norm=surface.norm)
m.set_array(data)
plt.colorbar(m)
plt.show()
There is a little bit of chaos in the code.
When specifying facecolors, there is no reason to supply a colormap, because the facecolors do not need to be retrieved from a colormap.
Colormaps range from 0 to 1. Your data ranges from 0 to 2. Hence half of the facecolors are just the same. So you first need to normalize the data to the (0,1)-range, e.g. using a Normalize instance, then you can apply the colormap.
norm = plt.Normalize(vmin=data.min(), vmax=data.max())
surface=ax.plot_surface(x, y, z, cstride=1, rstride=1,
facecolors=cm.jet(norm(data)))
For the colorbar you should then use the same colormap and the same normalization as for the plot itself.
m = cm.ScalarMappable(cmap=cm.jet,norm=norm)
m.set_array(data)
Complete code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
# prepare the sphere surface
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Z axis')
phi = np.linspace(0,2*np.pi, 50)
theta = np.linspace(0, np.pi, 25)
x=np.outer(np.cos(phi), np.sin(theta))
y=np.outer(np.sin(phi), np.sin(theta))
z=np.outer(np.ones(np.size(phi)), np.cos(theta))
# prepare function to plot
PHI=np.outer(phi,np.ones(np.size(theta)))
THETA=np.outer(np.ones(np.size(phi)),theta)
data = PHI/np.pi
# plot
norm = plt.Normalize(vmin=data.min(), vmax=data.max())
surface=ax.plot_surface(x, y, z, cstride=1, rstride=1,
facecolors=cm.jet(norm(data)))
# add colorbar
m = cm.ScalarMappable(cmap=cm.jet,norm=norm)
m.set_array(data)
plt.colorbar(m)
plt.show()

Label is Missing from matplotlib legend

I'm plotting subplots with matplotlib and the legend does not show up for some plots.
In this example, the scatter plot legend does not show up.
import numpy as np
import matplotlib
from matplotlib import pyplot as plt
from matplotlib.legend_handler import HandlerLine2D
from matplotlib.patches import Rectangle, Circle
fig = plt.figure()
plt.cla()
plt.clf()
x = np.arange(5) + 1
y = np.full(5, 10)
fig, subplots = plt.subplots(2, sharex=False, sharey=False)
subplots[0].bar(x, y, color='r', alpha=0.5, label='a')
scat = subplots[0].scatter(x, y-1, color='g', label='c')
subplots[0].set_yscale('log')
subplots[1].bar(x, y, color='r', alpha=0.5, label='a')
x = [2, 3]
y = [4, 4]
subplots[1].bar(x, y, color='b', alpha=1, label='b')
subplots[1].set_yscale('log')
plt.legend(loc='center left', bbox_to_anchor=(1, 0.5), handler_map={scat: HandlerLine2D(numpoints=4)})
plt.show()
Here is what I tried as a workaround:
p1 = Rectangle((0, 0), 1, 1, fc="r", alpha=0.5)
p2 = Rectangle((0, 0), 1, 1, fc="b")
p3 = Circle((0, 0), 1, fc="g")
legend([p1, p2, p3], ['a', 'b', 'c'], loc='center left', bbox_to_anchor=(1, 0.5))
I really prefer to fix this without the workaround so if anyone knows how to fix it please let me know.
Also, an issue with the workaround is that the Circle object still appears as a bar on the legend.
plt.legend starts with a gca() (which returns the current axes):
# from pyplot.py:
def legend(*args, **kwargs):
ret = gca().legend(*args, **kwargs)
So calling plt.legend will only get you a legend on your last subplot. But it is also possible to call e.g. ax.legend(), or in your case subplots[0].legend(). Adding that to the end of your code gives me a legend for both subplots.
Sample:
for subplot in subplots:
subplot.legend(loc='center left', bbox_to_anchor=(1, 0.5))