I am trying to plot simple function r = 3*sin(2*theta) using matplotlib:
import numpy as np
import matplotlib.pyplot as plt
theta = np.arange(0,2*np.pi,0.01)
r = 3.0*np.sin(2.0*theta)
ax = plt.subplot(111, projection='polar')
ax.plot(theta, r)
plt.show()
This is the result I get (it is not correct):
This is what I expect to see (wolfram alpha):
Am I missing something?
Thanks!
this patches the polar plot for neg r
import numpy as np
import matplotlib.pyplot as plt
theta = np.arange(0,2*np.pi,0.01)
r = 3.0*np.sin(2.0*theta)
theta = theta + (1 - np.sign(r))*np.pi/2 # add pi to points with negative r values
r = np.abs(r) # make all r values postive to fake out matplotlib
ax = plt.subplot(111, projection='polar')
ax.plot(theta, r)
plt.show()
Related
I'm trying to graph a the values of a variable vs time in a polar graph countour (see the image of what i'm trying to do).
The emotion_list is the score for detected emotion
import numpy as np
import matplotlib.pyplot as plt
emotion_list = [0.0,0.2,0.3,0.3,0.0,0.2,0.0]
rad_arr = np.radians(np.arange(0,360,7))
r_arr = emotion_list
def func(r, theta):
return r*np.sin(theta)
r, theta = np.meshgrid(r_arr, rad_arr)
print(r)
print(theta)
values = func(r, theta)
fig, ax = plt.subplots(subplot_kw=dict(projection = 'polar'))
ax.contourf(theta, r, values, cmap = 'Spectral_r')
But the graphic i got is not as expected.
The graph i would like to is something like this:
Graphic wanted
Thanks everyone for your help.
A contour plot will not work well with repeated values. Try this
import numpy as np
import matplotlib.pyplot as plt
emotion_list = [0.0,0.2,0.3]
rad_arr = np.radians(np.arange(0,360,len(emotion_list)))
r_arr = emotion_list
def func(r, theta):
return r*np.sin(theta)
r, theta = np.meshgrid(r_arr, rad_arr)
print(r)
print(theta)
values = func(r, theta)
fig, ax = plt.subplots(subplot_kw=dict(projection = 'polar'))
ax.contourf(theta, r, values, cmap = 'Spectral_r')
plt.show()
The repeated values in emotion_list were removed and the shape of the rad_arr array is now connected to the length of the emotion_list array.
I have a 3d plot made using matplotlib. I now want to fill the vertical space between the drawn line and the x,y axis to highlight the height of the line on the z axis. On a 2d plot this would be done with fill_between but there does not seem to be anything similar for a 3d plot. Can anyone help?
here is my current code
from stravalib import Client
import matplotlib as mpl
import numpy as np
import matplotlib.pyplot as plt
... code to get the data ....
mpl.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
zi = alt
x = df['x'].tolist()
y = df['y'].tolist()
ax.plot(x, y, zi, label='line')
ax.legend()
plt.show()
and the current plot
just to be clear I want a vertical fill to the x,y axis intersection NOT this...
You're right. It seems that there is no equivalent in 3D plot for the 2D plot function fill_between. The solution I propose is to convert your data in 3D polygons. Here is the corresponding code:
import math as mt
import matplotlib.pyplot as pl
import numpy as np
import random as rd
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
# Parameter (reference height)
h = 0.0
# Code to generate the data
n = 200
alpha = 0.75 * mt.pi
theta = [alpha + 2.0 * mt.pi * (float(k) / float(n)) for k in range(0, n + 1)]
xs = [1.0 * mt.cos(k) for k in theta]
ys = [1.0 * mt.sin(k) for k in theta]
zs = [abs(k - alpha - mt.pi) * rd.random() for k in theta]
# Code to convert data in 3D polygons
v = []
for k in range(0, len(xs) - 1):
x = [xs[k], xs[k+1], xs[k+1], xs[k]]
y = [ys[k], ys[k+1], ys[k+1], ys[k]]
z = [zs[k], zs[k+1], h, h]
#list is necessary in python 3/remove for python 2
v.append(list(zip(x, y, z)))
poly3dCollection = Poly3DCollection(v)
# Code to plot the 3D polygons
fig = pl.figure()
ax = Axes3D(fig)
ax.add_collection3d(poly3dCollection)
ax.set_xlim([min(xs), max(xs)])
ax.set_ylim([min(ys), max(ys)])
ax.set_zlim([min(zs), max(zs)])
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_zlabel("z")
pl.show()
It produces the following figure:
I hope this will help you.
I am trying to plot a graph given the adjancecy matrix and the coordinates of the nodes with this code below, using matplotlib. Yet when I vizualize the graph, it's not the same as the adjancecy matrix, and mainly some edges are missing. Any insights?
NB: for now I am only plotting 2D Graph so my Z are 0, so if you have any other idea on how to do so (maybe with networkx) I'll appreciate your help too
from scipy.spatial import Delaunay
import numpy as np
#from numpy import sin, cos, sqrt
import matplotlib.tri as mtri
#from sklearn import preprocessing
import mpl_toolkits.mplot3d as plt3d
import matplotlib.pyplot as plt
plt.rcParams.update({'figure.max_open_warning': 0})
plt.switch_backend('agg')
def draw_surface( points_coord, adj):
'''points_coord.shape: (num_points, coord=3),
adj.shape:(num_points,num_points)'''
name= 'img'
fig = plt.figure(figsize=(12,10))
# Plot the surface.
ax = fig.add_subplot(1, 1, 1, projection='3d')
#ax.plot_trisurf(triang, z, cmap=cm.jet)#cmap=plt.cm.CMRmap)
x = points_coord[:,0]
y = points_coord[:,1]
if len(points_coord) == 3:
z = points_coord[:,2]
else:
z = np.zeros_like(points_coord[:,0])
max_val = np.max(adj)
list_edges = []
#plot lines from edges
for i in range(adj.shape[0]):
for j in range(i,adj.shape[1]):
if adj[i][j]:
line = plt3d.art3d.Line3D([x[i],x[j]], [y[i],y[j]], [z[i],z[j]], \
linewidth=0.4, c="black", alpha = round( adj[i,j], 4 ))
list_edges.append((i,j))
ax.add_line(line)
ax.scatter(x,y,z, marker='.', s=15, c="blue", alpha=0.6)
#ax.view_init(azim=25)
plt.axis('off')
plt.show()
plt.savefig(name+'.png', dpi=120)
plt.clf()
I am trying to plot z transforms of some signals using the mpl_toolkits in python, but the output is totally blank. What am I doing wrong? The input numpy arrays have non-zero values. Here is my code:
import numpy as np
import matplotlib.pyplot as plt
import math
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
# initialize r and theta
r = 10
theta = r*np.linspace(-math.pi,math.pi,100)
theta = np.meshgrid(theta,theta)[0]
# calculate z
z = r*(np.cos(theta) + 1j*np.sin(theta))
# calculate z transform for first signal
xs1 = np.abs(z/(z-2))
# calculate z transform for second signal
xs2 = np.abs((np.power(z,3)+2*np.power(z,2)+3*z+3)/np.power(z,3))
# plot the transforms
fig1 = plt.figure(0)
ax1 = fig1.add_subplot(111, projection='3d')
fig2 = plt.figure(1)
ax2 = fig2.add_subplot(111, projection='3d')
ax1.plot_surface(z.real,z.imag,xs1,cmap = cm.coolwarm)
ax2.plot_surface(z.real,z.imag,xs2,cmap = cm.coolwarm)
plt.show()
Here is one of the output:
I am trying to circular contour lines around an array of random values of radius. The result should be a bunch of concentric circles with different radius. However I am not too sure how to plot the theta so that for each radius, all values of theta is plotted to form a line.
import random
import numpy as np
r= sort(np.array([ random.random()*5 for i in arange(100) ]))
len(r)
theta = [t for t in linspace(0,2*pi,100)]
ax = plt.subplot(111, polar=True)
ax.plot(theta, r, 'o',color='r', linewidth=3)
ax.set_rmax(2.0)
ax.grid(True)
Thank you.
Here is a one-line addition that I think does what you want:
import random
import numpy as np
import matplotlib.pyplot as plt
r= np.sort(np.array([ random.random()*5 for i in np.arange(100) ]))
len(r)
theta = [t for t in np.linspace(0,2*np.pi,100)]
ax = plt.subplot(111, polar=True)
ax.plot(theta, r, 'o',color='r', linewidth=3)
ax.set_rmax(2.0)
ax.grid(True)
[ax.plot(theta, rcirc*np.ones(100)) for rcirc in r.max()*np.random.rand(5)]
plt.show()
A quick-and-dirty way to do it would be to use np.linspace to effectively draw a polygon (as I think you were attempting to do):
import numpy as np
from matplotlib import pyplot as plt
# some random radii
r = np.random.rand(10)
# 1000 angles linearly spaced between 0 and 2pi
t = np.linspace(0, 2 * np.pi, 1000)
# broadcast r against t to make each a (1000, 10) array
r, t = np.broadcast_arrays(r[None, :], t[:, None])
# plot the lines
fig, ax = plt.subplots(1, 1, subplot_kw={'polar':True})
ax.plot(t, r, '-')
I'm sure there must be a more elegant way to do this, though.