How to add space for xticklabels in python? - python

all, I'm using Matplotlib to plot a polarbar. But the ticks are overlapped.
Does anybody know how to avoid this? Thanks!
from pylab import *
import matplotlib.pyplot as plt
from cf.plot import BoundaryNorm,getBoundCmap
from matplotlib import colors
fig = figure(figsize=(8,8))
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8], polar=True)
N = 8
theta = np.arange(0.0, 2*np.pi, 2*np.pi/N)
radii = ones((1,N)).squeeze()
width = 2*np.pi/N
bars = ax.bar(theta, radii, width=width, bottom=0.6)
listBnd = [0,3,6,9,12,15,18,21,24]
mcolors = plt.cm.Spectral(linspace(0,1,N))
cmap = colors.ListedColormap(mcolors)
for r,bar in zip(arange(1,N+1), bars):
bar.set_facecolor(cmap(r-1))
xlabels = array([0,21,18,15,12,9,6,3])
ax.xaxis.labelpad=50
ax.set_xticks(theta)
ax.set_xticklabels(xlabels,rotation=270,fontsize='60')
ax.xaxis.set_label_coords(0.5,-0.5)
ax.set_yticklabels([])
grid([])
show()

First off, let's clean up your code a bit. You have a lot of things that don't make sense. (For example, why generate a list of colors from the colormap, then create another colormap, then get the colors you originally generated from the other colormap?)
In addition, you're setting a lot of parameters that probably don't do what you think they do. (For example, the labelpad for an axis controls the padding for the axis label (e.g. xlabel), not for the ticks.)
With that in mind, your code might look something like this:
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection='polar')
N = 8
theta = np.arange(0.0, 2*np.pi, 2*np.pi/N)
radii = np.ones(N)
width = 2 * np.pi / N
bars = ax.bar(theta, radii, width=width, bottom=0.6)
colors = plt.cm.Spectral(np.linspace(0, 1, N))
for color, bar in zip(colors, bars):
bar.set_facecolor(color)
xlabels = np.array([0,21,18,15,12,9,6,3])
ax.set_xticks(theta)
ax.set_xticklabels(xlabels, rotation=270, fontsize=60)
ax.set_yticklabels([])
ax.grid(False)
plt.show()
Which generates a figure similar to the following:
Basically, you want to use the frac kwarg to ax.set_thetagrids to change the radial position of the theta tick labels. (This is a bit hidden, but it's the easiest way to do it.)
In addition, I'm using fig.tight_layout to resize things so that the tick labels don't wind up outside of the figure boundaries.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection='polar')
N = 8
theta = np.arange(0.0, 2*np.pi, 2*np.pi/N)
radii = np.ones(N)
width = 2 * np.pi / N
bars = ax.bar(theta, radii, width=width, bottom=0.6)
colors = plt.cm.Spectral(np.linspace(0, 1, N))
for color, bar in zip(colors, bars):
bar.set_facecolor(color)
xlabels = np.array([0,21,18,15,12,9,6,3])
ax.set_thetagrids(np.degrees(theta), xlabels, frac=1.2,
rotation=270, fontsize=60)
ax.set_yticklabels([])
ax.grid(False)
fig.tight_layout()
plt.show()

Related

matplotlib set_aspect(num) on an axis doesn't resize display box in a gridspec

I'm plotting an image with their two projections (x and y) in a GridSpec. When I use the set_aspect on the central image, the image size box isn't resized for its minimal size (without blank) as you can see below. Does somebody have a solution to resolve this case?
Matplotlib 3.0.2, Python 3.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
plt.rcParams['toolbar'] = 'toolmanager'
matplotlib.use('Qt5Agg')
ldata = np.random.random((256, 256))
xhisto = np.sum(ldata, axis=0)
yhisto = np.sum(ldata, axis=1)
fig = plt.figure()
gs = plt.GridSpec(2, 2, height_ratios=[10,1], width_ratios=[3,30], wspace=0.1, hspace=0.1)
ax_image = plt.subplot(gs[1])
ax_histoy = plt.subplot(gs[0], sharey=ax_image)
ax_histox = plt.subplot(gs[3], sharex=ax_image)
plt.subplots_adjust(right=0.8)
colorAx = plt.axes([0.85, 0.4, 0.02, 0.45])
im = ax_image.imshow(ldata, cmap='jet', interpolation='none', aspect='auto')
ax_histox.plot(xhisto)
ax_histoy.plot(yhisto, range(256))
ax_image.invert_yaxis()
ax_image.tick_params(labelbottom=False, labelleft=False)
ax_histoy.spines['right'].set_visible(False)
ax_histoy.spines['bottom'].set_visible(False)
ax_histox.spines['right'].set_visible(False)
ax_histox.spines['top'].set_visible(False)
ax_histoy.set_ylim(1,256)
ax_histox.set_xlim(1,256)
ax_histox.set_xlabel('X')
ax_histoy.set_ylabel('Y')
ax_image.set_title('Matplotlib - Plot 2D')
ax_histoy.tick_params(axis='x',labelsize=8,labelrotation=90)
ax_histox.tick_params(axis='y',labelsize=8)
ax_histoy.xaxis.tick_top()
ax_histox.yaxis.tick_left()
plt.colorbar(im, cax = colorAx)
ax_image.set_aspect(0.5)
plt.show()
I try to find a solution for resizing the height of the projection on the left
Using the example as you explain give the save result with a ratio different as 1:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
# Fixing random state for reproducibility
np.random.seed(19680801)
# the random data
x = np.random.randn(1000)
y = np.random.randn(1000)
fig, axScatter = plt.subplots(figsize=(5.5, 5.5))
# the scatter plot:
axScatter.scatter(x, y)
axScatter.set_aspect(0.3)
# create new axes on the right and on the top of the current axes
# The first argument of the new_vertical(new_horizontal) method is
# the height (width) of the axes to be created in inches.
divider = make_axes_locatable(axScatter)
axHistx = divider.append_axes("top", 1.2, pad=0.1, sharex=axScatter)
axHisty = divider.append_axes("right", 1.2, pad=0.1, sharey=axScatter)
# make some labels invisible
axHistx.xaxis.set_tick_params(labelbottom=False)
axHisty.yaxis.set_tick_params(labelleft=False)
# now determine nice limits by hand:
binwidth = 0.25
xymax = max(np.max(np.abs(x)), np.max(np.abs(y)))
lim = (int(xymax/binwidth) + 1)*binwidth
bins = np.arange(-lim, lim + binwidth, binwidth)
axHistx.hist(x, bins=bins)
axHisty.hist(y, bins=bins, orientation='horizontal')
# the xaxis of axHistx and yaxis of axHisty are shared with axScatter,
# thus there is no need to manually adjust the xlim and ylim of these
# axis.
axHistx.set_yticks([0, 50, 100])
axHisty.set_xticks([0, 50, 100])
plt.show()
Result with axes_grid
Could it solved with axes_grid ???

Set space between axis label and axis

Is there a way of specifying the position of axis labels?
labelpad sets the space between tick labels and the axis label.
Since the width of tick labels is unknown it appears to thus be impossible to precisely position axis labels.
Here is a MWE where I would like to have the ylabels of both subplots to be vertically aligned:
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
np.random.seed(19680801)
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
fig, axs = plt.subplots(2,1)
for ax in axs:
n, bins, patches = ax.hist(x, 50, normed=1, facecolor='g', alpha=0.75)
ax.set_ylabel('Probability $y$')
ax.grid(True)
ax.set_yticklabels([ r'\$\num{{{:g}}}\$'.format(item) for item in ax.get_yticks().tolist() ])
fig.show()
I tried this, but it does not work:
fig.canvas.draw()
ylabelposition = ax.yaxis.label.get_position()
ax.set_yticklabels([ r'\$\num{{{:g}}}\$'.format(item) for item in ax.get_yticks().tolist() ])
ax.yaxis.label.set_position(ylabelposition)

Hide radial tick labels matplotlib

I'm trying to plot a polar plot with this code:
import numpy as np
import matplotlib.pylab as plt
def power(angle, l, lam):
return 1/(lam) * ((np.cos(np.pi*l*np.cos(angle)/lam) - np.cos(np.pi*l/lam))/np.sin(angle))**2
fig = plt.figure(1)
ax = fig.add_subplot(111, projection='polar')
theta = np.linspace(0.001, 2*np.pi, 100)
P1 = power(theta, 1, 5)
ax.plot(theta, P1, color='r', linewidth=3)
plt.savefig('1.png')
and I get this plot:
I would like to change 2 things. The first and more important one is to hide the radial tick labels (I just want to show the general form of the plot).
If possible, how can I choose the vertical axis to correspond to 0°?
Thanks for your help.
You can use set_yticklabels() to remove the radial ticks and set_theta_zero_location() to change the zero location:
fig = plt.figure(1)
ax = fig.add_subplot(111, projection='polar')
ax.plot(theta, P1, color='r', linewidth=3)
ax.set_yticklabels([])
ax.set_theta_zero_location('N')
plt.show()
You might also want to change the direction of the azimuthal axis:
ax.set_theta_direction(-1)
You can set the theta zero position with ax.set_theta_zero_location('N').
To modify the r tick labels, you could do something like
for r_label in ax.get_yticklabels():
r_label.set_text('')
If you want to remove them entirely, do ax.set_yticklabels([]).
More methods can be found in the PolarAxes documentation.

Matplotlib Half color axis

I am using matplotlib to make some plots and I have run into a few difficulties that I need help with.
problem 1) In order to keep a consistent colorscheme I need to only use half of the color axis. There are only positive values, so I want the zero values to be green, the mid values to be yellow and the highest values to be red. The color scheme that most closely matches this is gist_rainbow_r, but I only want the top half of it.
problem 2) I can't seem to figure out how to get the colorbar on the right hand side of the plot to show up or how to get it to let me label the axes.
If it helps, I am using the latest version of Anaconda wth the latext version of matplotlib
cmap = plt.get_cmap('gist_rainbow_r')
edosfig2 = plt.figure(2)
edossub2 = edosfig.add_subplot(1,1,1)
edossub2 = plt.contourf(eVec,kints,smallEDOS,cmap=cmap)
edosfig2.show()
If you have a specific set of colors that you want to use for you colormap, you can build it based on those. For example:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
cmap = LinearSegmentedColormap.from_list('name', ['green', 'yellow', 'red'])
# Generate some data similar to yours
y, x = np.mgrid[-200:1900, -300:2000]
z = np.cos(np.hypot(x, y) / 100) + 1
fig, ax = plt.subplots()
cax = ax.contourf(x, y, z, cmap=cmap)
cbar = fig.colorbar(cax)
cbar.set_label('Z-Values')
plt.show()
However, if you did just want the top half of some particularly complex colormap, you can copy a portion of it by evaluating the colormap over the range you're interested in. For example, if you wanted the "top" half, you'd evaluate it from 0.5 to 1:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# Evaluate an existing colormap from 0.5 (midpoint) to 1 (upper end)
cmap = plt.get_cmap('gist_earth')
colors = cmap(np.linspace(0.5, 1, cmap.N // 2))
# Create a new colormap from those colors
cmap2 = LinearSegmentedColormap.from_list('Upper Half', colors)
y, x = np.mgrid[-200:1900, -300:2000]
z = np.cos(np.hypot(x, y) / 100) + 1
fig, axes = plt.subplots(ncols=2)
for ax, cmap in zip(axes.flat, [cmap, cmap2]):
cax = ax.imshow(z, cmap=cmap, origin='lower',
extent=[x.min(), x.max(), y.min(), y.max()])
cbar = fig.colorbar(cax, ax=ax, orientation='horizontal')
cbar.set_label(cmap.name)
plt.show()

matplotlib - change marker color along plot line

I would like to plot a 2d data set with matplotlib such that the marker color for each data point is different. I found the example on multicolored lines (http://matplotlib.org/examples/pylab_examples/multicolored_line.html). However, this does not seem to work when plotting a line with markers.
The solution I came up with individually plots every point:
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np
# The data
x = np.linspace(0, 10, 1000)
y = np.sin(2 * np.pi * x)
# The colormap
cmap = cm.jet
# Create figure and axes
fig = plt.figure(1)
fig.clf()
ax = fig.add_subplot(1, 1, 1)
# Plot every single point with different color
for i in range(len(x)):
c = cmap(int(np.rint(x[i] / x.max() * 255)))
ax.plot(x[i], y[i], 'o', mfc=c, mec=c)
ax.set_xlim([x[0], x[-1]])
ax.set_ylim([-1.1, 1.1])
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.draw()
plt.show()
# Save the figure
fig.savefig('changing_marker_color.png', dpi=80)
The resulting plot looks like as it should but the plotting gets really slow and I need it quite fast. Is there a clever trick to speed up the plotting?
I believe you can achieve this with ax.scatter:
# The data
x = np.linspace(0, 10, 1000)
y = np.sin(2 * np.pi * x)
# The colormap
cmap = cm.jet
# Create figure and axes
fig = plt.figure(1)
fig.clf()
ax = fig.add_subplot(1, 1, 1)
c = np.linspace(0, 10, 1000)
ax.scatter(x, y, c=c, cmap=cmap)
Scatter accepts c as a sequence of floats which will be mapped to colors using the cmap.
Using timeit I get a 10 fold decrease in time (about 1.25 secs for the original method and 76.8 ms here)

Categories

Resources