I am trying to generate symmetrical circular images using python, but I couldn't find an easy way to do it.
Here is an example sort of what I want:
So far, I listed the processes, but I couldn't find an easy way to implement them.:
Is there a simple way to do it?
I would use a polar plot, then it's just a matter of calculating the coordinates. For this, I am using np.linspace and I combine a division of the trigonometric circle, the same points shifted by 10°, and zeros:
import matplotlib.pyplot as plt
from itertools import chain
fig, ax = plt.subplots(subplot_kw={'projection': 'polar'})
ax.grid(False)
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
n = 6
# division of the circle
a = np.linspace(0, 2*np.pi, n+1)
# angles
theta = list(chain.from_iterable(zip(a, np.zeros(n+1), a+(np.pi/180*10))))
# distance to center
r = np.tile([1,0,1], n+1)
# plotting line
ax.plot(theta, r)
# plotting fill (needs an extra (0,0) point)
ax.fill(theta+[0], list(r)+[0], alpha=0.2)
example:
example with a loop
import matplotlib.pyplot as plt
import numpy as np
from itertools import chain
fig, axes = plt.subplots(ncols=4, nrows=3, subplot_kw={'projection': 'polar'})
axes = axes.flatten()
def plot_shape(ax, n=3, delta=np.pi/180*10):
ax.grid(False)
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
a = np.linspace(0, 2*np.pi, n+1)-delta/2
theta = list(chain.from_iterable(zip(a, np.zeros(n+1), a+delta)))
r = np.tile([1,0,1], n+1)
ax.plot(theta, r)
ax.fill(theta+[0], list(r)+[0], alpha=0.2)
for i in range(len(axes)):
axes[i].set_title(f'n = {i+1}')
plot_shape(axes[i], n=i+1)
plt.tight_layout()
Related
I haven't found an answer to this yet: I have a grid defined in a text file with four columns: (lon,lat,depth,slip). Each row is a grid point.
I can generate a scatter plot of these points using the following simple code:
# Main imports:
import numpy as np
from pylab import *
from mpl_toolkits.mplot3d import Axes3D
# Read the grid:
points = np.loadtxt("grid.txt")
# Retrieve parameters from the grid:
lon = points[:,0]
lat = points[:,1]
depth = points[:,2]
slip = points[:,3]
# 3-D plot of the model:
fig = figure(1)
ax = fig.add_subplot(111, projection='3d')
p = ax.scatter(lon, lat, depth, c=slip, vmin=0, vmax=max(slip), s=30, edgecolor='none', marker='o')
fig.colorbar(p)
title("Published finite fault in 3-D")
ax.set_xlabel("Longitude [degrees]")
ax.set_ylabel("Latitude [degrees]")
ax.set_zlabel("Depth [km]")
ax.invert_zaxis()
jet()
grid()
show()
And I get the following figure:
What I want to do is to be able to interpolate those points to create a "continuous" surface grid and plot it in both 2-D and 3-D plots. Therefore, somehow I've to consider all (lon,lat,depth,slip) in the interpolation. I'd appreciate your suggestions. Thanks in advance!
I'm a bit late, but if your data grid is properly ordered, you could resolve your iusse using plot_surface reshaping your 1D data to 2D.
An example supposing you're using a 10x10 grid:
# Main imports:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# Set the fourth dimension`
color_dimension = slip.reshape(10,10)
# normalize the colours
minn, maxx = color_dimension.min(), color_dimension.max()
norm = matplotlib.colors.Normalize(minn, maxx)
# color map
m = plt.cm.ScalarMappable(norm=norm, cmap='hot')
m.set_array([])
fcolors = m.to_rgba(color_dimension)
# plot
fig = plt.figure()
ax = fig.gca(projection='3d')
#reshape 1D data to 2D
g=ax.plot_surface(lat.reshape(10, 10), lon.reshape(10, 10), depth.reshape(10, 10), cmap='hot',rstride=1, cstride=1, facecolors=fcolors, vmin=minn, vmax=maxx, shade=False)
cbar=fig.colorbar(g,aspect=50)
cbar.set_label('slip', rotation=270, fontsize=14)
title("Published finite fault in 3-D")
ax.set_xlabel("Longitude [degrees]")
ax.set_ylabel("Latitude [degrees]")
ax.set_zlabel("Depth [km]")
ax.invert_zaxis()
plt.show()
I have a 1D array for some quantity, say T. I have data points (X, Y) to be plotted with errorbars and colorcoded with T.
I am plotting errorbars as:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.pylab as pylab
import matplotlib
X = np.linspace(0, 10, 50)
Y = np.random.normal(0, 1, 50)
E = np.random.normal(0, 0.1, 50)
norm = matplotlib.colors.Normalize(vmin=0, vmax=0.5)
c_m = matplotlib.cm.jet
s_m = matplotlib.cm.ScalarMappable(cmap=c_m, norm=norm)
s_m.set_array([])
plt.figure()
for i in range(0, len(Y)):
plt.errorbar(X[i], Y[i], color=s_m.to_rgba(E[i]), yerr=[E[i], E[i]], capsize=3, ls='none')
plt.grid()
plt.show()
This doesn't seem to work. Says :
err must be [ scalar | N, Nx1 or 2xN array-like ]
For plt.plot, if I have say N curves, each with M points, and I have to colorcode each curve by T, (dimensions: X[M], Y[N][M], T[N])
I do the following:
norm = matplotlib.colors.Normalize(
vmin=0,
vmax=32)
# choose a colormap
c_m = matplotlib.cm.jet
# create a ScalarMappable and initialize a data structure
s_m = matplotlib.cm.ScalarMappable(cmap=c_m, norm=norm)
s_m.set_array([])
plt.figure()
for i in range(0, N):
plt.plot(X, Y[i], color=s_m.to_rgba(T[i]))
plt.grid()
plt.show()
This scheme works for plot! But does not seem to work with errorbar and 1D arrays.
However, I am not really sure how far the comparison is good since array dimensions are different in plot (2D) and errorbar (1D) case.
EDIT:
Got the solution. It does not relate to colorbar at all. Just that yerr array needs 2XN array.
Hence yerr=[[E[i]], [E[i]]] fixes it.
I still don't see the problem. Replacing plt.plot with plt.errorbar is working just fine:
import matplotlib.pyplot as plt
import matplotlib.colors
import matplotlib.cm
import numpy as np
N=3
x=np.arange(10)
Y = np.random.rand(len(x),N)
a = np.ones_like(x)*0.1
T = np.array([5,12,27])
plt.figure()
norm = matplotlib.colors.Normalize(vmin=0,vmax=32)
# choose a colormap
c_m = matplotlib.cm.jet
# create a ScalarMappable and initialize a data structure
s_m = matplotlib.cm.ScalarMappable(cmap=c_m, norm=norm)
s_m.set_array([])
for i in range(0, N):
plt.errorbar(x, Y[:,i], yerr=[a,a], color=s_m.to_rgba(T[i]), capsize=3, ls='none')
plt.grid()
plt.grid()
plt.show()
I am looking to make a plot similar to the one found here, with the simple difference that I would like to to set the distance from the center for each point. Ie, given a slice of the plot is a circle, where I would like each of the points to be at a definable distance from the center.
What I a starting with, given a simple modification of the previously mentioned answer:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib
import numpy as np
from scipy.interpolate import interp1d
from matplotlib import cm
from matplotlib import pyplot as plt
step = 0.04
maxval = 1.0
fig = plt.figure()
ax = Axes3D(fig)
# u here would define the desired distance from radial axis
# u=np.array([0,1,2,1,0,2,4,6,4,2,1])
v=np.array([4,4,6,3,6,4,1,4,4,4,4])
r=np.array([0,1,2,3,4,5,6,7,8,9,10])
f=interp1d(r,u)
# walk along the circle
p = np.linspace(0,2*np.pi,len(r))
R,P = np.meshgrid(r,p)
# transform them to cartesian system
X,Y = R*np.cos(P),R*np.sin(P)
Z=f(R)
ax.scatter(X, Y, Z)#, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xticks([])
fig.savefig(str(output_prefix + '3d..png'), dpi=(200))
What I would like to plot (apologies for the blurred sketch):
I have tried using interp2d to add the u variable commented out above, but no luck. Changing Z to the array u threw the error that X, Y, and Z must be the same size ("Argument 'zs' must be of same size as 'xs' ", understandably as X and Y are now interpolated) What do I need to do? Any tips would be appreciated!
I don't know exactly what you meant in your question.
I made v to be the offset of the center of the circles in x-axis.
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.interpolate import interp1d
from matplotlib import pyplot as plt
step = 0.04
maxval = 1.0
fig = plt.figure()
ax = Axes3D(fig)
# v here would define the desired distance from radial axis
u=np.array([0,1,2,1,0,2,4,6,4,2,1])
v=np.array([4,4,6,3,6,4,1,4,4,4,4])
r=np.array([0,1,2,3,4,5,6,7,8,9,10])
f=interp1d(r,u)
# walk along the circle
V = np.tile(v, (len(u), 1))
p = np.linspace(0,2*np.pi,len(r))
R,P = np.meshgrid(r,p)
# transform them to cartesian system
X,Y = V + R*np.cos(P),R*np.sin(P)
Z=f(R)
ax.scatter(X, Y, Z)#, rstride=1, cstride=1, cmap=cm.jet)
ax.set_xticks([])
plt.show()
I have 3xN array positions that vary in time for a particle. I want to take the coordinates at each time point, plot that position as a point on a 3D axis and then repeat, creating an animation.
I can create a single image of this effect using matplotlib's Axes3D
x_a = particle_a[:,0]
y_a = particle_a[:,1]
z_a = particle_a[:,2]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x_a, y_a, z_a, c='b')
plt.show
'particle_a' is just an array of shape (N,3) where N is the number of timepoints.
How can I animate this?
Adapting this example from the matplotlib site you can represent a particle moving in 3D with:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d as p3
import matplotlib.animation as animation
def make_helix(n):
theta_max = 8 * np.pi
theta = np.linspace(0, theta_max, n)
x, y, z = theta, np.sin(theta), np.cos(theta)
helix = np.vstack((x, y, z))
return helix
def update_lines(num, dataLines, lines) :
for line, data in zip(lines, dataLines) :
line.set_data(data[0:2, num-1:num])
line.set_3d_properties(data[2,num-1:num])
return lines
# Attach 3D axis to the figure
fig = plt.figure()
ax = p3.Axes3D(fig)
n = 100
data = [make_helix(n)]
lines = [ax.plot(data[0][0,0:1], data[0][1,0:1], data[0][2,0:1], 'o')[0]]
# Setthe axes properties
ax.set_xlim3d([0.0, 8*np.pi])
ax.set_xlabel('X')
ax.set_ylim3d([-1.0, 1.0])
ax.set_ylabel('Y')
ax.set_zlim3d([-1.0, 1.0])
ax.set_zlabel('Z')
ax.set_title('3D Test')
# Creating the Animation object
ani = animation.FuncAnimation(fig, update_lines, n, fargs=(data, lines),
interval=50, blit=False)
plt.show()
(replace helix with your own data and set the axes limits accordingly).
I have a figure showing the contourf plot and another showing a plot i've made earlier and I want to plot both on the same figure what should I do?
Here is the code of my contourf plot:
import pylab as pl
from pylab import *
import xlrd
import math
import itertools
from matplotlib import collections as mc
import matplotlib.pyplot as plt
import copy as dc
import pyexcel
from pyexcel.ext import xlsx
import decimal
x_list = linspace(0, 99, 100)
y_list = linspace(0, 99, 100)
X, Y = meshgrid(x_list, y_list, indexing='xy')
Z = [[0 for x in range(len(x_list))] for x in range(len(y_list))]
for each_axes in range(len(Z)):
for each_point in range(len(Z[each_axes])):
Z[len(Z)-1-each_axes][each_point] = power_at_each_point(each_point, each_axes)
figure()
CP2 = contourf(X, Y, Z, cmap=plt.get_cmap('Reds'))
colorbar(CP2)
title('Coverage Plot')
xlabel('x (m)')
ylabel('y (m)')
show()
This is the code of my previously plotted plot:
lc = mc.LineCollection(lines, linewidths=3)
fig, ax = pl.subplots()
ax.add_collection(lc)
ax.autoscale()
ax.margins(0.05)
#The code blow is just for drawing the final plot of the building.
Nodes = xlrd.open_workbook(Node_file_location)
sheet = Nodes.sheet_by_index(0)
Node_Order_Counter = range(1, sheet.nrows + 1)
In_Node_Order_Counter = 0
for counter in range(len(Node_Positions_Ascending)):
plt.plot(Node_Positions_Ascending[counter][0], Node_Positions_Ascending[counter][1], marker='o', color='r',
markersize=6)
pl.text(Node_Positions_Ascending[counter][0], Node_Positions_Ascending[counter][1],
str(Node_Order_Counter[In_Node_Order_Counter]),
color="black", fontsize=15)
In_Node_Order_Counter += 1
#Plotting the different node positions on our plot & numbering them
pl.show()
Without your data we can't see what the plot is supposed to look like, but I have some general recommendations.
Don't use pylab. And if you absolutely must use it, use it within its namespace, and don't do from pylab import *. It makes for very sloppy code - for example, linspace and meshgrid are actually from numpy, but it's hard to tell that when you use pylab.
For complicated plotting, don't even use pyplot. Instead, use the direct object plotting interface. For example, to make a normal plot on top of a contour plot, (such as you want to do) you could do the following:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x = np.linspace(1, 5, 20)
y = np.linspace(2, 5, 20)
z = x[:,np.newaxis] * (y[np.newaxis,:])**2
xx, yy = np.meshgrid(x, y)
ax.contourf(xx, yy, z, cmap='Reds')
ax.plot(x, 0.2*y**2)
plt.show()
Notice that I only used pyplot to create the figure and axes, and show them. The actual plotting is done using the AxesSubplot object.