I'm trying to draw something called the bloch sphere, but I got its image even when it's not supposed to happen. I wrote the following codes.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from itertools import product, combinations
class quantum_gates:
def __init__(self,x2,y2,z2):
x2 = input("x:")
y2 = input("y:")
z2 = input("z:")
x2 = float(x2)
y2 = float(y2)
z2 = float(z2)
self.x2 = x2
self.y2 = y2
self.z2 = z2
if self.x2**2 + self.y2**2 + self.z2**2 != 1:
print("Wrong input(x^2+y^2+z^2 has to be 1)")
else:
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_aspect("equal")
u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
x = np.cos(u)*np.sin(v)
y = np.sin(u)*np.sin(v)
z = np.cos(v)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
ax.plot_wireframe(x, y, z, color="black")
ax.quiver(0,0,0,x2,y2,z2,color="red")
For example, when I put quantum_gates(2,3,1),which is self.x2^2 + self.y2^2 + self.z2^2 != 1, I get the image of the sphere and a red arrow.
What am I supposed to do to get them only when self.x2^2+self^y2+self.z2^2 = 1?
Related
I need to make the blue circle move in a straight line with animation.
The straight line code needs to stay as is. I just can't figure out the code for object animation.
The circle can be in any shape and colour it just need to move from point A to point B in a straight line.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import pyplot as plt, patches
img=np.ones((200,200,3))
c=plt.Circle((50, 100))
def DrawLine(x1,y1,x2,y2):
dx = abs(x2-x1)
dy = abs(y2-y1)
if x1<x2:
xs=1
else:
xs=-1
if y1<y2:
ys=1
else:
ys=-1
x=x1
y=y1
p=2*dy-dx
if dx>dy:
while x!=x2:
x=x+xs
if p > 0:
y=y+ys
p=p+2*dy-2*dx
else:
p=p+2*dy
img[y,x]= 0
DrawLine(150,100,50,100)
fig = plt.figure()
plt.imshow(img)
plt.gca().add_artist(c)
plt.show()
Matplotlib has animations for this purpose:
import numpy as np
from matplotlib import pyplot as plt, animation
img = np.ones((200, 200, 3))
def DrawLine(x1, y1, x2, y2):
dx = abs(x2 - x1)
dy = abs(y2 - y1)
if x1 < x2:
xs = 1
else:
xs = -1
if y1 < y2:
ys = 1
else:
ys = -1
x = x1
y = y1
p = 2 * dy - dx
if dx > dy:
while x != x2:
x = x + xs
if p > 0:
y = y + ys
p = p + 2 * dy - 2 * dx
else:
p = p + 2 * dy
img[y, x] = 0
DrawLine(150, 100, 50, 100)
fig, ax = plt.subplots()
ax.imshow(img)
# define animation function
def animate(i):
c = plt.Circle((50+i % 100, 100))
circle = ax.add_artist(c)
return circle,
# define animation properties, see
# https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.FuncAnimation.html
ani = animation.FuncAnimation(fig, animate, interval=20, blit=True)
plt.show()
I try to draw a sphere to represent a qubit using matplotlib
import numpy as np
import matplotlib.pyplot as plt
theta = [0, np.pi]
phi = [0, 2* np.pi]
N=100
theta_array = np.linspace(theta[0], theta[1], N)
phi_array = np.linspace(phi[0], phi[1], N)
theta_grid, phi_grid = np.meshgrid(theta_array,phi_array)
x = np.sin(theta_grid) * np.cos(phi_grid)
y = np.sin(theta_grid) * np.sin(phi_grid)
z = np.cos(theta_grid)
fig = plt.figure(figsize=(6,6))
ax = fig.gca(projection='3d')
ax.plot_surface(x, y, z, rstride=1, cstride=1, shade=False,linewidth=0)
plt.show()
I want to add tube arrows on the sphere with directions parallel with xyz axis, like this:
I am not an expert in matplotlib, so it's seem pretty tough to me. Can anyone help me? thanks in advance!
You can use the quiver function to to what you want.
See code below:
import numpy as np
import matplotlib.pyplot as plt
theta = [0, np.pi]
phi = [0, 2* np.pi]
N=100
theta_array = np.linspace(theta[0], theta[1], N)
phi_array = np.linspace(phi[0], phi[1], N)
theta_grid, phi_grid = np.meshgrid(theta_array,phi_array)
x = np.sin(theta_grid) * np.cos(phi_grid)
y = np.sin(theta_grid) * np.sin(phi_grid)
z = np.cos(theta_grid)
fig = plt.figure(figsize=(6,6))
ax = fig.gca(projection='3d')
ax.view_init(azim=60)
ax.plot_surface(x, y, z, rstride=1, cstride=1, shade=False,linewidth=0)
#Set up arrows
ax.quiver(1,0,0,1,0,0,color = 'k', alpha = .8, lw = 3) #x arrow
ax.text(2.4,0,0,'Sx',fontsize=20)
ax.quiver(0,1,0,0,1,0,color = 'k', alpha = .8, lw = 3)#y arrow
ax.text(0,2.4,0,'Sy',fontsize=20)
ax.quiver(0,0,1,0,0,1,color = 'k', alpha = .8, lw = 3)#z arrow
ax.text(-0.3,0,1.8,'Sz',fontsize=20)
plt.show()
And the output gives:
I am trying to shade the area between two curves that I have plotted.
This is what I plotted.
Using the following code.
plt.scatter(z1,y1, s = 0.5, color = 'blue')
plt.scatter(z2,y2, s = 0.5, color = 'orange')
I tried using plt.fill_between() but for this to work I need to have the same data on the x_axis (would need to do something like plt.fill_between(x,y1,y2)).
Is there any other function that might help with this or am I just using fill_between wrong.
You can try with:
plt.fill(np.append(z1, z2[::-1]), np.append(y1, y2[::-1]), 'lightgrey')
For example:
import numpy as np
import matplotlib.pyplot as plt
x1 = np.array([1,2,3])
y1 = np.array([2,3,4])
x2 = np.array([2,3,4,5,6])
y2 = np.array([1,2,3,4,5])
# plt.plot(x1, y1, 'o')
# plt.plot(x2, y2, 'x')
plt.scatter(x1, y1, s = 0.5, color = 'blue')
plt.scatter(x2, y2, s = 0.5, color = 'orange')
plt.fill(np.append(x1, x2[::-1]), np.append(y1, y2[::-1]), 'lightgrey')
plt.show()
Try this code:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(0.0, 2, 0.01)
y1 = np.sin(2 * np.pi * x)
y2 = 1.2 * np.sin(4 * np.pi * x)
fig, (ax1) = plt.subplots(1, sharex=True)
ax1.fill_between(x, 0, y1)
ax1.set_ylabel('between y1 and 0')
I want to plot multiple lines in a 3d axis plot.
I'm plotting the trajectory of a light ray, each line should be colored depending on the time of propagation for each path.
I want to plot them independently, since I saved them in a binary three structure in which any ray may follow two different trajectories.
I used Line3DCollection, but it doesn't seem to be the right way.
In few words,
import numpy as np
x = np.linspace(0,1,100)
y = x
z = x
t = np.linspace(0,1,100)
#here I need to plot these points coloring them in function of t
x1 = np.linspace(1,2,100)
y1 = x
z1 = x
t1 = np.linspace(1,2,100)
#I need to plot also this used the same colorbar used for former values
x2 = -np.linspace(1,2,100)
y2 = x
z2 = x
t2 = np.linspace(1,2,100)
#idem
having all the lines colored with the same colorbar scale, like this
plot.
I tried with the following but the output is not like I expected
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Line3DCollection
x = np.linspace(0,1,100)
y = x
z = x
t = np.linspace(0,1,100)
points = np.array([x,y,z]).transpose().reshape(-1,1,3)
segs = np.concatenate([points[:-1],points[1:]],axis=1)
lc = Line3DCollection(segs, cmap=plt.get_cmap('jet'))
lc.set_array(t)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.add_collection3d(lc)
x1 = np.linspace(1,2,100)
y1 = x1
z1 = x1
t1 = np.linspace(1,2,100)
points1 = np.array([x1,y1,z1]).transpose().reshape(-1,1,3)
segs1 = np.concatenate([points1[:-1],points1[1:]],axis=1)
lc = Line3DCollection(segs1, cmap=plt.get_cmap('jet'))
lc.set_array(t1)
lc.update_scalarmappable()
ax.add_collection3d(lc)
x2 = np.linspace(1,2,100)
y2 = -x2+2
z2 = -x2+2
t2 = np.linspace(1,2,100)
points2 = np.array([x2,y2,z2]).transpose().reshape(-1,1,3)
segs2 = np.concatenate([points2[:-1],points2[1:]],axis=1)
lc = Line3DCollection(segs2, cmap=plt.get_cmap('jet'))
lc.set_array(t1)
lc.update_scalarmappable()
ax.add_collection3d(lc)
ax.set_xlim(0, 2)
ax.set_ylim(0, 2)
ax.set_zlim(0, 2)
fig.colorbar(lc)
plt.show()
plotting this plot
Thanks in advance
I have the following code which produces a cylinder-like object using matplotlib:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
nphi,nz=7,20
r=1 # radius of cylinder
phi = np.linspace(0,360, nphi)/180.0*np.pi
z= np.linspace(0,1.0,nz)
print z
cols=[]
verts2 = []
for i in range(len(phi)-1):
cp0= r*np.cos(phi[i])
cp1= r*np.cos(phi[i+1])
sp0= r*np.sin(phi[i])
sp1= r*np.sin(phi[i+1])
for j in range(len(z)-1):
z0=z[j]
z1=z[j+1]
verts=[]
verts.append((cp0, sp0, z0))
verts.append((cp1, sp1, z0))
verts.append((cp1, sp1, z1))
verts.append((cp0, sp0, z1))
verts2.append(verts)
value=np.random.rand()
#print value
col=plt.cm.rainbow(0.9)
#print col
cols.append(col)
poly3= Poly3DCollection(verts2, facecolor=cols,edgecolor = "none" )
poly3.set_alpha(0.8)
ax.add_collection3d(poly3)
ax.set_xlabel('X')
ax.set_xlim3d(-1, 1)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, 1)
ax.set_zlabel('Z')
ax.set_zlim3d(0, 1)
plt.show()
This code produces the following image:
However as you can see the are sharp corners in the figure. Is there anyway to make these edges rounder so that the figure looks like a proper cylinder with a circular cross-section as opposed to a hexagonal cross-section?
The third argument to
np.linspace
controls how many values you want it to generate. Thus, nphi controls the
number of values in phi, and nz controls the number of values in z:
phi = np.linspace(0,360, nphi)/180.0*np.pi
z = np.linspace(0,1.0,nz)
So if you increase nphi, then you'll get more points along the circle:
cp0 = r*np.cos(phi[i])
sp0 = r*np.sin(phi[i])
For example, try changing nphi, nz = 7,20 to nphi, nz = 70, 2.
Note that there is no need for nz to be greater than 2 since the sides of the
cylinder are flat in the z direction.
By the way, the double for-loop can be replaced by:
PHI, Z = np.meshgrid(phi, z)
CP = r * np.cos(PHI)
SP = r * np.sin(PHI)
XYZ = np.dstack([CP, SP, Z])
verts = np.stack(
[XYZ[:-1, :-1], XYZ[:-1, 1:], XYZ[1:, 1:], XYZ[1:, :-1]], axis=-2).reshape(-1, 4, 3)
So, for example,
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
nphi, nz = 70, 2
r = 1 # radius of cylinder
phi = np.linspace(0, 360, nphi) / 180.0 * np.pi
z = np.linspace(0, 1.0, nz)
PHI, Z = np.meshgrid(phi, z)
CP = r * np.cos(PHI)
SP = r * np.sin(PHI)
XYZ = np.dstack([CP, SP, Z])
verts = np.stack(
[XYZ[:-1, :-1], XYZ[:-1, 1:], XYZ[1:, 1:], XYZ[1:, :-1]], axis=-2).reshape(-1, 4, 3)
cmap = plt.cm.rainbow
cols = cmap(np.random.random())
poly3 = Poly3DCollection(verts, facecolor=cols, edgecolor="none")
poly3.set_alpha(0.8)
ax.add_collection3d(poly3)
ax.set_xlabel('X')
ax.set_xlim3d(-1, 1)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, 1)
ax.set_zlabel('Z')
ax.set_zlim3d(0, 1)
plt.show()
yields