I am trying to give a different to my grid along the x axis and the y axis.
Though when I call ax.grid it seems to hide the grid instead of configuring it.
import matplotlib.pyplot as plt
import numpy
x = numpy.arange(0, 1, 0.05)
y = numpy.power(x, 2)
fig = plt.figure()
ax = fig.gca()
ax.set_xticks(numpy.arange(0, 1, 0.1))
ax.set_yticks(numpy.arange(0, 1., 0.1))
ax.grid(axis='x', linestyle="-", linewidth=1) # doesn't work
ax.grid(axis='y', linestyle="--", linewidth=1) # doesn't work
plt.scatter(x, y)
plt.grid()
plt.show()
Without the ax.grid calls, the grid appears but the style is not what I want.
Just remove plt.grid works for me:
x = np.arange(0, 1, 0.05)
y = np.power(x, 2)
fig = plt.figure()
ax = fig.gca()
ax.set_xticks(np.arange(0, 1, 0.1))
ax.set_yticks(np.arange(0, 1., 0.1))
ax.grid(axis='x', linestyle="-", linewidth=1) # doesn't work
ax.grid(axis='y', linestyle="--", linewidth=1) # doesn't work
ax.scatter(x, y)
# plt.grid()
plt.show()
Output:
Related
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)
...
I am trying to make a visualization with logarithmic ticks on all sides of the box.
import numpy as np
import matplotlib.pyplot as plt
x = np.logspace(2, 5, 5)
y = 0.5*x**(-1/2)
y2 = 0.01*x**(-1/2)
y3 = 0.05*x**(-1/3)
fig, ax = plt.subplots()
ax.plot(x, y, 'o-', label="One")
ax.plot(x, y2, '*-', label="Two")
ax.plot(x, y3, '--', label="Three")
ax.set(
xlabel='Input',
xlim=(1e2, 1e5),
xscale='log',
ylabel='Output',
ylim=(1e-5, 1e-1),
yscale='log',
)
ax.tick_params(top=True, right=True) # <-- This didn't work how I expected.
ax.legend(loc='lower left');
I would like the associated minor tick marks on the top and right spine.
Any advice on how to make that happen?
Use the which parameter of Axes.tick_params:
ax.tick_params(which='both', top=True, right=True)
Output:
I'd like to be able to rotate the view of a hemisphere in a 3D matplotlib plot and have the shape show correctly,
Answers to set matplotlib 3d plot aspect ratio? used in the first example don't help as they address the aspect ratio of the plot window.
Question: In the second example I show that if I make the scales equal lengths (-1, 1), (-1, 1), (-0.5, 1.5) I can preserve the shape as I rotate the view, but is this the only way to preserve the shape under view rotation?
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
points = np.random.random((3, 1000)) - 0.5
points /= np.sqrt((points**2).sum(axis=0))
x, y, z = points[:, points[2] > 0.] # upper hemisphere
fig = plt.figure(figsize=plt.figaspect(0.5)) # https://stackoverflow.com/a/12371373/3904031
ax1 = fig.add_subplot(2, 1, 1, projection='3d')
ax1.plot(x, y, z, '.k')
ax1.view_init(0, 90)
ax1.set_title('view_init(0, 90)', fontsize=16)
ax2 = fig.add_subplot(2, 1, 2, projection='3d')
ax2.plot(x, y, z, '.k')
ax2.view_init(90, 0)
ax2.set_title('view_init(90, 0)', fontsize=16)
plt.show()
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
ax1.plot(x, y, z, '.k')
ax1.view_init(0, 90)
ax1.set_title('view_init(0, 90)', fontsize=16)
ax1.set_xlim(-1.0, 1.0)
ax1.set_ylim(-1.0, 1.0)
ax1.set_zlim(-0.5, 1.5)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
ax2.plot(x, y, z, '.k')
ax2.view_init(90, 0)
ax2.set_title('view_init(90, 0)', fontsize=16)
ax2.set_xlim(-1.0, 1.0)
ax2.set_ylim(-1.0, 1.0)
ax2.set_zlim(-0.5, 1.5)
plt.show()
Finally, per this answer:
Simple fix!
I've managed to get this working in version 3.3.1.
It looks like this issue has perhaps been resolved in PR#17172; You can use the ax.set_box_aspect([1,1,1]) function to ensure the aspect is correct (see the notes for the set_aspect function).
You first make the limits in all three axes the same either by adding bounding points (invisible dots beyond your data) to define a cube of equal dimensions, or just use set_xlim, set_ylim, set_zlim as I've done here.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
points = np.random.random((3, 1000)) - 0.5
points /= np.sqrt((points**2).sum(axis=0))
x, y, z = points[:, points[2] > 0.] # upper hemisphere
fig = plt.figure(figsize=plt.figaspect(0.5)) # https://stackoverflow.com/a/12371373/3904031
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
ax1.plot(x, y, z, '.k')
ax1.view_init(0, 90)
ax1.set_title('view_init(0, 90)', fontsize=16)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
ax2.plot(x, y, z, '.k')
ax2.view_init(90, 0)
ax2.set_title('view_init(90, 0)', fontsize=16)
for ax in (ax1, ax2):
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_zlim(-0.5, 1.5)
ax.set_box_aspect([1,1,1])
plt.show()
I have written a code that plot some points and lines on the xy plane. It plots everything for a given value of n. So for different n I get my desired plots. But I want to animate these plots for different values of n, say, for n=1, 2, ..., 100. But I cannot do this animation.
Can anyone here help me to do this? Thank you.. I paste my code here:
My Code
import matplotlib as mpl
mpl.rc('text', usetex = True)
mpl.rc('font', family = 'serif')
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
fig = plt.subplots()
ax = plt.axes(xlim=(-1.2, 1.2), ylim=(-1.2, 1.2))
plt.gca().set_aspect('equal', adjustable='box')
plt.style.use(['ggplot','dark_background'])
plt.rcParams['figure.figsize'] = (12, 8)
n = 10 #I want to animate this n.
p = 2
for k in range(0,n,1):
theta1 = np.pi + 2*k*np.pi / n
theta2 = np.pi + 2*p*k*np.pi / n
x, y = np.cos(theta1), np.sin(theta1)
x1, y1 = np.cos(theta2), np.sin(theta2)
plt.scatter(x, y, s=50, c='violet', zorder=3)
plt.plot([x,x1], [y,y1], color = 'w')
circle = plt.Circle((0, 0), 1, color='c', fill=False, lw = 1)
ax.add_artist(circle)
#Customize the axes and gridlines:
ax.grid(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
#TickMarks Customization:
ax.set_xticks([])
ax.set_yticks([])
#plt.savefig('nthRoots.png', format='png', dpi=1000,bbox_inches='tight')
plt.show()
Output
Is it possible to animate n over different values?
EDIT: Here I donot have only scatter plots ...so I cannot understand how to do this job using those links..!
My Attempt
#Animation.
import matplotlib as mpl
mpl.rc('text', usetex = True) #for LaTex notation in the Plot
mpl.rc('font', family = 'serif')
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
from matplotlib import animation, rc
rc('animation', html='html5')
fig = plt.subplots()
ax = plt.axes(xlim=(-1.2, 1.2), ylim=(-1.2, 1.2))
plt.gca().set_aspect('equal', adjustable='box')
plt.style.use(['ggplot','dark_background'])
plt.rcParams['figure.figsize'] = (12, 8)
p = 2
#Plotting Function:
def f(n):
for k in range(0,n,1):
theta1 = np.pi + 2*k*np.pi / n
theta2 = np.pi + 2*p*k*np.pi / n
x, y = np.cos(theta1), np.sin(theta1)
x1, y1 = np.cos(theta2), np.sin(theta2)
plt.scatter(x, y, s=50, c='violet', zorder=3)
plt.plot([x,x1], [y,y1], color = 'w')
circle = plt.Circle((0, 0), 1, color='c', fill=False, lw = 1)
ax.add_artist(circle)
#Customize the axes and gridlines:
ax.grid(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
#TickMarks Customization:
ax.set_xticks([])
ax.set_yticks([])
plt.show()
#Now I try to define a function for animating n in f(n)
def animate(n):
f(n)
anim = animation.FuncAnimation(fig, animate,
frames=100, interval=100, blit=True)
#anim.save('Wave.mp4', writer = 'ffmpeg', fps = 2, dpi=500,extra_args=['-vcodec', 'libx264'])
That's all I had... But this idea didn't work...I think I have to properly define animate(n).
Any suggestion...! thanks.
Several problems in your code (most are unrelated to animations)
rcParams need to be defined before creating the figure
plt.subplots returns a tuple of figure and axes.
The animation must return a sequence of artist objects when blitting is used. You might turn it off though
plt.show() should be called once at the end of the script.
Correcting for those you get
import matplotlib as mpl
mpl.rc('font', family = 'serif')
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Circle
from matplotlib import animation, rc
plt.rcParams['figure.figsize'] = (12, 8)
plt.style.use(['ggplot','dark_background'])
fig, ax = plt.subplots()
p = 2
#Plotting Function:
def f(n):
ax.clear()
ax.set(xlim=(-1.2, 1.2), ylim=(-1.2, 1.2))
ax.set_aspect('equal', adjustable='box')
for k in range(0,n,1):
theta1 = np.pi + 2*k*np.pi / n
theta2 = np.pi + 2*p*k*np.pi / n
x, y = np.cos(theta1), np.sin(theta1)
x1, y1 = np.cos(theta2), np.sin(theta2)
plt.scatter(x, y, s=50, c='violet', zorder=3)
plt.plot([x,x1], [y,y1], color = 'w')
circle = Circle((0, 0), 1, color='c', fill=False, lw = 1)
ax.add_artist(circle)
#Customize the axes and gridlines:
ax.grid(False)
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
#TickMarks Customization:
ax.set_xticks([])
ax.set_yticks([])
anim = animation.FuncAnimation(fig, f, frames=100, interval=100, blit=False)
plt.show()
I need to generate a plot with equal aspect in both axis and a colorbar to the right. I've tried setting aspect='auto', aspect=1, and aspect='equal' with no good results. See below for examples and the MWE.
Using aspect='auto' the colorbars are of the correct height but the plots are distorted:
Using aspect=1 or aspect='equal' the plots are square (equal aspect in both axis) but the colorbars are distorted:
In both plots the colorbars are positioned too far to the right for some reason. How can I get a square plot with colorbars of matching heights?
MWE
import numpy as np
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
def col_plot(params):
gs, i, data = params
xarr, yarr, zarr = zip(*data)[0], zip(*data)[1], zip(*data)[2]
xmin, xmax = min(xarr), max(xarr)
ymin, ymax = min(yarr), max(yarr)
#plt.subplot(gs[i], aspect='auto')
plt.subplot(gs[i], aspect=1)
#plt.subplot(gs[i], aspect='equal')
plt.xlim(xmin, xmax)
plt.ylim(xmin, xmax)
plt.xlabel('$x axis$', fontsize=20)
plt.ylabel('$y axis$', fontsize=20)
# Scatter plot.
cm = plt.cm.get_cmap('RdYlBu_r')
SC = plt.scatter(xarr, yarr, marker='o', c=zarr, s=60, lw=0.25, cmap=cm,
zorder=3)
# Colorbar.
ax0 = plt.subplot(gs[i + 1])
cbar = plt.colorbar(SC, cax=ax0)
cbar.set_label('$col bar$', fontsize=21, labelpad=-2)
# Generate data.
data0 = np.random.uniform(0., 1., size=(50, 3))
data1 = np.random.uniform(0., 1., size=(50, 3))
# Create the top-level container
fig = plt.figure(figsize=(14, 25))
gs = gridspec.GridSpec(4, 4, width_ratios=[1, 0.05, 1, 0.05])
# Generate plots.
par_lst = [[gs, 0, data0], [gs, 2, data1]]
for pl_params in par_lst:
col_plot(pl_params)
# Output png file.
fig.tight_layout()
plt.savefig('colorbar_aspect.png', dpi=300)
You can use an AxesDivider to do that. I have modified your code a bit to make use of an AxesDivider.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
def col_plot(data):
xarr, yarr, zarr = zip(*data)[0], zip(*data)[1], zip(*data)[2]
xarr = [2*x for x in xarr]
xmin, xmax = min(xarr), max(xarr)
ymin, ymax = min(yarr), max(yarr)
fig = plt.figure()
ax0 = fig.add_subplot(111, aspect='equal')
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
plt.xlabel('$x axis$', fontsize=20)
plt.ylabel('$y axis$', fontsize=20)
# Scatter plot.
cm = plt.cm.get_cmap('RdYlBu_r')
SC = ax0.scatter(xarr, yarr, marker='o', c=zarr, s=60, lw=0.25, cmap=cm,
zorder=3)
the_divider = make_axes_locatable(ax0)
color_axis = the_divider.append_axes("right", size="5%", pad=0.1)
# Colorbar.
cbar = plt.colorbar(SC, cax=color_axis)
cbar.set_label('$col bar$', fontsize=21, labelpad=-2)
# Generate data.
data0 = np.random.uniform(0., 1., size=(20, 3))
col_plot(data0)
And here is the result (I changed your data so it spans a range of [0, 2] in the x-direction for demonstration purposes):
On Joseph Long's blog there is the following nice solution.
1) Define a colorbar function as:
from mpl_toolkits.axes_grid1 import make_axes_locatable
def colorbar(mappable):
ax = mappable.axes
fig = ax.figure
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)
return fig.colorbar(mappable, cax=cax)
2) Call colorbar(thing) when you want to make a colorbar. In your case:
SC = ax0.scatter(xarr, yarr, marker='o', c=zarr, s=60, lw=0.25, cmap=cm,
zorder=3)
colorbar(SC)
3) And you get: