plt.imshow() circle with probability density inside - python

I'm trying to use plt.imshow to create an image of a circle of a specified radius and image resolution. In the future this code will also be implemented with certain probability distributions inside the circle, but for now I'm just worried about a uniform one. This is what I have (uniform distribution with plt.imshow but not in the shape of a circle):
mu= 500
kappa= 1
array = np.random.uniform(mu,kappa, size=(2**n, 2**n))
plt.imshow(array, cmap='magma')
plt.show()
it creates a distribution like this:
and my goal is to have an image like this:
not my best art, but you get the point.

You may use matplotlib's Circle patch (as described in this tutorial):
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Circle, PathPatch
circle = Circle((500, 500), 500, facecolor='none',
edgecolor=(0, 0.8, 0.8), linewidth=3, alpha=0.5)
fig, ax = plt.subplots(figsize=(6, 6))
n=10
mu= 500
kappa= 1
array = np.random.uniform(mu,kappa, size=(2**n, 2**n))
ax.add_patch(circle)
im = plt.imshow(array, cmap='magma')
im.set_clip_path(circle)
plt.show()
This returns:

Related

3d contour with 3 variables and 1 variable as colour

I have three variables for my plot and I colour by the fourth variable. I have made a scatter plot via the following code, but I want a contour plot. My code:
import numpy as np
import matplotlib.pyplot as plt
a=np.linspace(4.0,14.0,3)
b=np.linspace(0.5,2.5,3)
c=np.linspace(0.0,1.0,3)
d=np.random.rand(len(a),len(b),len(c)) #colour by this variable
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
z,y,x=np.meshgrid(c,a,b)
img = ax.scatter(x, y, z, c=d, cmap='RdGy')
fig.colorbar(img, pad=0.2).set_label('colour')
ax.set_xlabel('c')
ax.set_ylabel('a')
ax.set_zlabel('b')
I want a filled contour instead of scatter plot. I know mayavi.mlab has this feature, but I cannot import mlab for some reason. Is there an alternative, or is there a better way of presenting this data?
Here is how I would present this 3-dimensional data. Each plot is a cross-section through the cube. This makes sense intuitively.
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(4.0, 14.0, 3)
y = np.linspace(0.5, 2.5, 3)
z = np.linspace(0.0, 1.0, 3)
data = np.random.rand(len(x), len(y), len(z))
fig, axes = plt.subplots(len(z), 1, figsize=(3.5, 9),
sharex=True,sharey=True)
for i, (ax, d) in enumerate(zip(axes, data.swapaxes(0, 2))):
ax.contour(x, y, d)
ax.set_ylabel('y')
ax.grid()
ax.set_title(f"z = {z[i]}")
axes[-1].set_xlabel('x')
plt.tight_layout()
plt.show()
My advice: 3D plots are rarely used for serious data visualization. While they look cool, it is virtually impossible to read any data points with any accuracy.
Same thing goes for colours. I recommend labelling the contours rather than using a colour map.
You can always use a filled contour plot to add colours as well.

Rotate polar stereographic subplot

I am making a figure with subplots which are north polar stereographic projections. I also created a custom boundary shape to display subplot as a circle. However once reprojected, I want to be able to rotate the map, since my data is focusing on the US and thus I was hoping that each subplot would have the US facing "up," thus I would need to rotate it 270 degrees / -90 degrees.
Minimalistic code example pulled from cartopy example
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline # for notebook
map_projection = ccrs.NorthPolarStereo(central_longitude=0, )
data_projection = ccrs.PlateCarree()
theta = np.linspace(0, 2*np.pi, 100)
center, radius = [0.5, 0.5], 0.5 # by changing radius we can zoom in/out
verts = np.vstack([np.sin(theta), np.cos(theta)]).T
circle = mpl.path.Path(verts * radius + center)
plot_extent=[-179.9,180, 30, 90]
fig, ax1 = plt.subplots(1,1, figsize=(6,6), dpi=100, subplot_kw=dict(projection=map_projection))
ax1.set_boundary(circle, transform=ax1.transAxes)
ax1.coastlines(linewidths=1.0, color='grey')
ax1.add_feature(cfeature.BORDERS, linestyles='--', color='dimgrey', linewidths=0.8 )
ax1.set_extent(plot_extent, crs=ccrs.PlateCarree(),)
gl = ax1.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=1, color='gray', alpha=0.5, linestyle='--', zorder=10)
I haven't yet found any good examples or documentation for what I am trying to do, however I am new to using matplotlib/cartopy.
You need to set central_longitude=-90.
So:
map_projection = ccrs.NorthPolarStereo(central_longitude=-90)

How to color individual elements in matplotlib plot_trisurf

I have a triangular surface mesh, generated via marching cubes. I want to color the surface elements based on an arbitrary variable in my plot. I am currently using plot_trisurf, but as I read the documentation, it looks like the color is always based on the Z component, or else a constant? Can I not specify a color per element? Or is there a better plot routine to use? For example, something along the lines of the code below is what I am after, where the color is based on the 'value' output from the marching cubes. Thanks!
import numpy as np
import matplotlib.pyplot as plt
from skimage import measure
from skimage.draw import ellipsoid
from matplotlib import cm
# Generate a level set about zero of two identical ellipsoids in 3D
ellip_base = ellipsoid(6, 10, 16, levelset=True)
# Use marching cubes to obtain the surface mesh of these ellipsoids
verts, faces, normals, values = measure.marching_cubes_lewiner(ellip_double, 0)
fig = plt.figure(figsize=(20, 10))
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(verts[:, 0], verts[:,1], verts[:, 2], triangles=faces, cmap=cm.rainbow, color=values)
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
ax.set_xlim(0, 24)
ax.set_ylim(0, 20)
ax.set_zlim(0, 32)
plt.tight_layout()
plt.show()
As noted by JohanC, in this question they reset the face colors after the fact. This works for me, as I already have an array of colors defined.
# set the face colors of the Poly3DCollection
p3dc.set_fc(colors)

Compute area of isosurface

I'm analyzing several files containing volumetric data reported as Gaussian Cube File Format (click here for the description).
I created this script in Python to compute and represent the isosurfaces using numpy and skimage:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from skimage import measure
from skimage.draw import ellipsoid
import load_cube
# create an object and read in data from file
cube=load_cube.CUBE(gaussian_cube_file.cube)
# Obtain the surface mesh setting a specific isovalue (0.2)
verts, faces = measure.marching_cubes(cube.data, 0.2)
# Display resulting triangular mesh using Matplotlib.
fig = plt.figure(figsize=(10, 12))
ax = fig.add_subplot(111, projection='3d')
# Generate triangles
mesh = Poly3DCollection(verts[faces])
ax.add_collection3d(mesh)
ax.set_xlabel("x-axis: a = 6")
ax.set_ylabel("y-axis: b = 10")
ax.set_zlabel("z-axis: c = 16")
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
ax.set_zlim(0, 100)
plt.show()
Results from the previous script
The questions are: how I can compute the total area of all isosurfaces showed in the resulting plot? How I can color each triangle on the basis of its value?

plot many circles based on x,y,r being vectors in python

x,y are positions of the circles and r is the radius - all vectors.I want to plot them all at once. Something like:
import matplotlib.pyplot as plt
from matplotlib.patches Circle
#define x,y,r vectors
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
plt.Circle((x,y),r,color='r')
plt.show()
Thanks.
plt.scatter allows you to define a radius of the points plotted.
From the doc
matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o')
[...]
s:
size in points^2. It is a scalar or an array of the same length as x and y.
Playing with facecolor and edgecolor you should be able to get what you want
You can find an example in How to set_gid() for each bubble in matplot scatter chart?
I am not informed about the Circles patch, but here is how you can do it with the standard plot command:
import numpy as np
import matplotlib.pyplot as plt
x = np.array([0.2,0.4])
y = np.array([0.2,1.2])
r = np.array([0.5,0.3])
phi = np.linspace(0.0,2*np.pi,100)
na=np.newaxis
# the first axis of these arrays varies the angle,
# the second varies the circles
x_line = x[na,:]+r[na,:]*np.sin(phi[:,na])
y_line = y[na,:]+r[na,:]*np.cos(phi[:,na])
plt.plot(x_line,y_line,'-')
plt.show()
The basic idea is to give the plt.plot(...) command two 2D arrays. In that case they are interpreted as a list of plots. Espacially for many plots (=many circles) this is much faster, than plotting circle by circle.

Categories

Resources