Scatter plot with a circle in it - python

I was planning to do a scatter plot with 5000 data points with a line of unit circle in the same plot, but the code I have right now show a pretty small plot with huge dots in it. I tried to make this plot size larger but plt.figure(figsize=(12,12)) doesn't work....wonder what did I do wrong?
import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
x=scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
y=scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
a=np.cos(np.linspace(0, 2*np.pi, 200))
b=np.sin(np.linspace(0, 2*np.pi, 200))
plt.scatter(x,y)
plt.plot(a,b, color="red")
plt.figure(figsize=(12,12))
plt.show()

plt.figure() creates a new empty plot. You should call it before the other plotting functions
You can set a smaller dotsize, e.g plt.scatter(x, y, s=1). To force that the circle is shown as a circle, set an equal aspect ratio (set_aspect('equal')).
import numpy as np
import scipy.stats
import matplotlib.pyplot as plt
x = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
y = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
a = np.cos(np.linspace(0, 2 * np.pi, 200))
b = np.sin(np.linspace(0, 2 * np.pi, 200))
plt.figure(figsize=(12, 12))
plt.scatter(x, y, s=1)
plt.plot(a, b, color="red")
plt.gca().set_aspect('equal')
plt.show()
To change the figsize after the plot has been created, you can use:
fig = matplotlib.pyplot.gcf()
fig.set_size_inches(15, 15)
Matplotlib also provides a function to create a circle. Here is an example setting a semi-transparent facecolor:
import scipy.stats
import matplotlib.pyplot as plt
x = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
y = scipy.stats.uniform.rvs(loc=-1, scale=2, size=5000)
plt.figure(figsize=(12, 12))
plt.scatter(x, y, s=1)
ax = plt.gca()
ax.add_patch(plt.Circle((0, 0), 1, facecolor='#FF000011', edgecolor='red'))
ax.set_aspect('equal')
plt.show()

Related

Python matplotlib adjust colormap

This is what I want to create.
This is what I get.
This is the code I have written.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
x = np.linspace(-90, 90, 181)
y = np.linspace(-90, 90, 181)
x_grid, y_grid = np.meshgrid(x, y)
z = np.e**x_grid
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection="3d")
ax.plot_surface(x_grid, y_grid, z, cmap=cm.rainbow)
I also tried to normalize z and the colormap.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
import matplotlib as mpl
x = np.linspace(-90, 90, 181)
y = np.linspace(-90, 90, 181)
x_grid, y_grid = np.meshgrid(x, y)
z = np.e**x_grid
cmap = mpl.cm.rainbow
norm = mpl.colors.Normalize(vmin=0, vmax=1)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection="3d")
ax.plot_surface(x_grid, y_grid, z/np.max(z), norm=norm, cmap=cm.rainbow)
Question: How can I adjust the colormap to make it less discrete and more continuous for these simultaneously tiny and large values in z?
Welcome to Stackoverflow!!
Your problem is related to the fact that you are working with exponential numbers, but you're using a linear colormap. For x=90 you have z=1.2e+39, reaaaally large.
You were very close with your second attempt! I just changed 1 line in there, instead of
norm = mpl.colors.Normalize(vmin=0, vmax=1)
I used
norm = mpl.colors.LogNorm()
And the result I got was the following:
Now, you can tweak this as much as you like in order to get the colors you want :) Just don't forget that your colormap should be normalized in a logarithmic fashion, so that it counters the exponential behaviour of your function in this case.
Hope this helps!

python - how do I fix interpolate grid origin issues in matplotlib?

I have a data set with a small sample size of data. For example:
My code looks something like this:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.interpolate import Rbf
df=pd.read_csv('test.csv')
df.head()
extent = x_extent = x_min, x_max, y_min, y_max = [df["X"].min()-1000, df["X"].max()+1000, df["Y"].min()-1000, df["Y"].min()+1000]
grid_x, grid_y = np.mgrid[x_min:x_max:100, y_min:y_max:100]
rbfi=Rbf(df["X"], df["Y"], df["Total"])
di=rbfi(grid_x, grid_y)
plt.scatter(grid_x, grid_y, s=10)
plt.figure(figsize=(15,15))
plt.imshow(di.T, origin="lower", extent=extent)
c2 = plt.scatter(df["X"], df["Y"], s=60, c=df["Total"], edgecolor='#ffffff66')
plt.colorbar(c2, shrink=0.6)
plt.show()
the result:
The result is a scatter plot of my points that appear to be in the correct place, but the interpolated grid is not covering the scatter points. So I think this has something to do with my origin not being correct, but I don't know how to fix this.
Two approaches here, one with a Delaunay triangulation, the other using the Radial Basis Function. Snippet and figure below.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.tri import Triangulation
from scipy.interpolate import Rbf
rng = np.random.default_rng()
X = rng.random(size=(15))
Y = rng.random(size=(15))
Total = rng.random(size=(15))
fig, (ax, bx) = plt.subplots(nrows=1, ncols=2, num=0, figsize=(16, 8))
tri = Triangulation(X, Y)
tctrf = ax.tricontourf(tri, Total)
gridY, gridX = np.mgrid[np.amin(Y):np.amax(Y):100 * 1j,
np.amin(X):np.amax(X):100 * 1j]
rbfi = Rbf(X, Y, Total, function='linear')
iTotal = rbfi(gridX, gridY)
bx.contourf(gridX, gridY, iTotal)
scat = ax.scatter(X, Y, s=60, c=Total, edgecolor='black')
fig.colorbar(scat, ax=ax)
scat = bx.scatter(X, Y, s=60, c=Total, edgecolor='black')
fig.colorbar(scat, ax=bx)
ax.set_aspect('equal')
bx.set_aspect('equal')
fig.tight_layout()
fig.savefig('so.png')
plt.show()

How do I create a colormap plot that can make a sphere in matplotlib 3d look like half i bright (look like the earth is illuminated on one side)

I am trying to create a 3D sphere in matplotlib and have it color like one side of the sphere is illuminated by the sun.
I have tried using matplotlib colormaps.
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_axis_off()
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))
PHI=np.outer(phi,np.ones(np.size(theta)))
THETA=np.outer(np.ones(np.size(phi)),theta)
data = PHI/np.pi
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)))
surface=ax.plot_surface(x, y, z, cstride=1, rstride=1,
facecolors=cm.binary(norm(data)),cmap=plt.get_cmap('jet'))
plt.show()
I am expecting a sphere that looks something like this:
Or basically something that looks like the earth with the day side and the night side
But instead my results are something like this:
current plot from the above code
You need to use LightSource package:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import LightSource
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_axis_off()
phi = np.linspace(0,2*np.pi, 100)
theta = np.linspace(0, np.pi, 50)
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))
PHI=np.outer(phi,np.ones(np.size(theta)))
THETA=np.outer(np.ones(np.size(phi)),theta)
data = PHI/np.pi
norm = plt.Normalize(vmin=data.min(), vmax=data.max())
# use Light Source
ls = LightSource(0, 0)
# create rgb shade
rgb = ls.shade(x, cmap=cm.Wistia, vert_exag=0.1, blend_mode='soft')
# blend shade
bsl = ls.blend_hsv(rgb, np.expand_dims(x*0.8, 2))
# plot surface
surface = ax.plot_surface(x, y, z, cstride=1, rstride=1, facecolors=bsl,
linewidth=0, antialiased=False, shade=False)
plt.show()
Output:

Creating a graph with 2 planes and colormaps via Python

I have two 2D arrays and I want to use to produce an image similar to the one that fallows, just with different limits on the axis.
Here is my attempt so far:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(-2.01, 2.01)
ax.set_ylim(-2.01, 2.01)
ax.set_zlim(-2.01, 2.01)
cmap = plt.cm.gray
im = ax.imshow(np.asarray(array1), cmap=cmap)
im.remove()
fig.colorbar(im)
plt.show()
The arrays I have, (array1 and array2) are two dimensional with sizes n by n. Any help or a point in the right direction will be greatly appreciated!
With help of Matplotlib - Plot a plane and points in 3D simultaneously, I am able to achieve this:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_zlim(0, 1)
ax.set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1])
ax.set_yticks([0, 0.5, 1])
ax.set_zticks([0, 0.2, 0.4, 0.6, 0.8, 1])
cmap = plt.cm.gray
#plot vertical surface
y = 0.5
xx, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(xx, y, zz, cmap=cmap, alpha=0.5)
x = 0.2
yy, zz = np.meshgrid(np.linspace(0,1,10), np.linspace(0,1,10))
p = ax.plot_surface(x, yy, zz, cmap=cmap, alpha=0.5)
fig.colorbar(p)
plt.show()
Note that I didn't use normal or dot just as another question do, because here you want to plot vertical planes.
Here's what I got(I'm working on the right occlusion):

End ticks in colorbar - matplotlib

I am trying to plot a colorbar in Python using the matplotlib libraries. The plot works well, but the color bar wont show the end ticks on the color bar.
Using the following command plots the colorbar properly, but I only have ticks ranging from -1.6 to +1.6 ( the top and bottom ticks are absent). The range of my data is from -2 to +2.
fig.colorbar(surf, shrink=1, aspect=12)
This is seen in the following figure:
I tried using the command:
cbar.set_ticks([-2,-1,0,1,2]);
But that also failed to get the correct result.
UPDATE:
I tried using the ticks=[-2,0,2] parameter, but that did not work as well. This is a snippet of my plotting code:
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
CHI = np.linspace(-45, 45, 35);
M = np.linspace(0, 1, 35)
CHI, M = np.meshgrid(CHI, M)
R = 2*M*np.sin( 2 * np.deg2rad(CHI) )
surf = ax.plot_surface(CHI, M, R, rstride=1, cstride=1, cmap=cm.hsv,linewidth=0, antialiased=False)
ax.set_xlim(-45,45)
cbar = plt.colorbar(surf, shrink=1, aspect=12, ticks=[-2,-1,0,1,2])
plt.show()
This produces the following plot:
As seen, the colorbar lacks the end ticks, viz. -2 and 2
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
CHI = np.linspace(-45, 45, 35);
M = np.linspace(0, 1, 35)
CHI, M = np.meshgrid(CHI, M)
R = 2*M*np.sin( 2 * np.deg2rad(CHI) )
surf = ax.plot_surface(CHI, M, R, rstride=1, cstride=1, cmap=cm.hsv,linewidth=0, antialiased=False)
surf.set_clim([-2, 2]) # <- this is the important line
ax.set_xlim(-45,45)
cbar = plt.colorbar(surf, shrink=1, aspect=12, ticks=[-2,-1,0,1,2])
plt.show()
Something is going wrong with the auto-scaling (I would guess issues with floating point equality tests), if you explicitly set the clim to [-2, 2] it works.
You should be able to set the ticks parameter when calling plt.colorbar:
import matplotlib.pyplot as plt
import numpy as np
fig, ax = plt.subplots()
cmap = plt.get_cmap('jet')
data = np.random.randint(-2,3, size=(10,10))
im = ax.imshow(data, interpolation='nearest', cmap=cmap)
cbar = plt.colorbar(im, ticks=[-2,-1,0,1,2])
plt.show()

Categories

Resources