Drawing a logarithmic spiral in three axes in Python - python

I try to draw a logarithmic spiral in the form of a spring in three axes.
Using the parametric equations:
x=a*exp(b*th)*cos(th)
y=a*exp(b*th)*sin(th)
Using the code:
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from math import exp,sin,cos
from pylab import *
mpl.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
n=100
a=0.5
b=0.20
th=np.linspace(0, 500, 10000)
x=a*exp(b*th)*cos(th)
y=a*exp(b*th)*sin(th)
ax.plot(x, y)
ax.legend()
plt.show()
I get:
However, I would like to stretch the spiral along the Z axis to get a result similar to the following, but using the logarithmic spiral as the basis:
How can you do it? How do you modify the function by adding a condition to the Z axis?

Which z to take it's a bit up to you. From the plot itself it's hard to say but my guess is that it's linear (the simplest option).
Taking your code and adding the z axis you can do something like this
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
from math import exp,sin,cos
from pylab import *
mpl.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
a=0.05
b=0.10
# took the liberty of reducing the max value for th
# as it was giving you values of the order of e42
th=np.linspace(0, 50, 10000)
x=a*exp(b*th)*cos(th)
y=a*exp(b*th)*sin(th)
z=np.linspace(0,2, 10000) # creating the z array with the same length as th
ax.plot(x, y, z) # adding z as an argument for the plot
ax.legend()
plt.show()
You can play with your a and b parameters to get the elliptical shape you want. You can also play with the definition of z to make it exponential, or logarithmic in growth.. or something else entirely.
BTW, your imports are a bit redundant and probably some funtions from one package are being shadowed by another package.

Since 95% of the points of the spiral are condensed in a single point in the middle of the plot it would make sense to restrict the plotted range to something like
th=np.linspace(475, 500, 10000)
Then using a linear range of z values would directly give you the desired curve in the plot, by simply specifying that range in the plot function, plot(x,y,z).
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d')
a=0.5
b=0.20
th=np.linspace(475, 500, 10000)
x=a*np.exp(b*th)*np.cos(th)
y=a*np.exp(b*th)*np.sin(th)
z = np.linspace(0,2, len(th))
ax.plot(x, y, z)
#ax.legend()
plt.show()
Note that I cleaned up the imports here. E.g. if you import cos from math but later import everything (*) from pylab into the namespace, the function cos that is used is the numpy cos function, not the one from math (the math cos function would not work here anyways). In general: don't use pylab at all.

Related

How to plot marker at beggining and end points using matplotlib

How can I automate a code so that I can place a marker for the starting and end points of this plot using matplotlib.pyplot?
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 9, 9)
y = x**2
A simple way would be just to overplot 2 points (being the begining and end points) ontop of your current plot. Using plt.figure(), we can have two plots ontop of each other.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 9, 9)
y = x**2
plt.figure()
plt.plot(x,y)
plt.scatter([x[0],x[-1]], [y[0],y[-1]])
Futhermore, this can be automatated by declare your own function which plots two plots on top automatically:
def plot(x,y):
plt.figure()
plt.plot(x,y)
plt.scatter([x[0],x[-1]], [y[0],y[-1]])

How to plot multiple parametric plots in a single figure?

I need to plot a family of parametric curves in a single figure for each alpha values as mentioned in the code
import numpy as np
from sympy import *
from sympy.plotting import plot_parametric
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
a=45
t = symbols('t')
for alpha in np.arange(0.5,3,.1):
M=a*sqrt(cos(2*t)+sqrt(pow(alpha,4)+pow(sin(2*t),2)))
x = M*cos(t)
y = M*sin(t)
plot_parametric(x, y, (t, 0, 2*pi))
The code returns a sequence of 2D plots for each alpha value. Instead, I want to plot the whole set of plots in one figure, something like this image attached
Any solution?
from numpy import arange, cos, linspace, pi, sin, sqrt
from matplotlib.pyplot import colorbar, Normalize, show, subplots
from matplotlib.cm import ScalarMappable, viridis
a=45
t= linspace(0, 2*pi, 2001)
norm = Normalize(vmin=0.5, vmax=3)
cmap = viridis
sm = ScalarMappable(cmap=cmap, norm=norm)
fig, (ax_xy, ax_tM) = subplots(1, 2, figsize=(10, 4), constrained_layout=1)
for alpha in arange(0.5,3,.1):
color = cmap(norm(alpha))
M=a*sqrt(cos(2*t)+sqrt(pow(alpha,4)+pow(sin(2*t),2)))
x = M*cos(t)
y = M*sin(t)
ax_tM.plot(t, M, color=color)
ax_xy.plot(x, y, color=color)
colorbar(sm, aspect=40)
show()

Showing end point of the 3d line: Python 3D plot

I made a 3D plot using the following code in python. Here three arrays x, y and z are used for the plot. I want to show the last point of the arrays (or the end point of the 3D line) in the plot. I used the approach I would use in 2d plotting, i.e., I asked for plotting only the last points of each array using this command ax.plot(x[-1],y[-1],z[-1],'o'). But it doesn't work.
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
x=np.linspace(0,2*np.pi)
y=np.sin(x)
z=np.cos(x)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(x, y, z, lw=1)
ax.plot(x[-1],y[-1],z[-1],'o') # This line doesn't work
plt.show()
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import
x=np.linspace(0,2*np.pi)
y=np.sin(x)
z=np.cos(x)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(x, y, z, lw=1)
ax.scatter(x[-1],y[-1],z[-1],'-') # This should do the job
plt.show()
Add Color and Label
ax.scatter(x[-1],y[-1],z[-1],'-',c="yellow",label="End Point")
plt.legend()
plt.show()
Additional explanation on why you were having an error:
You were telling python to draw you a ax.plot for 1 point. Which is impossible, because you cant draw a line using 1 point only. Therefore, you tell it to draw a scatter.

Matplotlib: transformation of variables for narrow orbit

I have an annoyingly narrow orbit in phase space that looks like this:
What kind of transformation of the variables can I do to get a nice circular orbit in this case?
My code is this:
import numpy as np
import matplotlib.pylab as plt
x,y = np.loadtxt("data.txt").T
plt.plot(x,y)
plt.show()
The data can be found here - link
I'm not sure if this is what you're after. What you can do is shift one of the two coordinates by the quarter of a circle and normalize to the other coordinate.
import numpy as np
import matplotlib.pylab as plt
x,y = np.loadtxt("data/orbit.txt").T
y = np.roll(y, len(y)//4)
y = (y-y.mean())*((x.max()-x.min())/(y.max()-y.min())) +y.mean()
fig, (ax, ax2) = plt.subplots(ncols=2)
ax.set_aspect("equal")
ax.plot(x,y)
t = np.linspace(0,2*np.pi, len(x))
ax2.plot(t,x-x.mean())
ax2.plot(t,y-y.mean())
plt.show()

How to make a 3D plot in matplotlib from data z=f(x,y) read from file

I need to create a 3D plot in matplotlib. I am reading Z values from a text file formated as 1D array. This data represents value for every point on a 50x50 square. So first 50 values are for points (0,0),(1,0)..(49,0), next 50 are for (0,1),(1,1) and so on. So far i have written the following code:
import matplotlib.pyplot as plt
import numpy as np
fp=open(path,"r")
a=fp.read()
buffer=""
data=[]
for i in a:
if i != ' ':
buffer=buffer+i
else:
data.append(float(buffer))
buffer=""
fp.close()
values=data[50*50:50*50*2]
x=np.linspace(0,50,50)
y=np.linspace(0,50,50)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_trisurf(x, y, values)
plt.show()
But of course it is not working. I searched the Internet for some clues but without any success. Can someone show me how I should done it? I would be more than grateful.
First, you forgot to import Axes3D: import matplotlib.pyplot as plt.
Second, you code has strange meaningless line: values[50*50*nb:50*50*(nb+1)] and indentation is wrong in your code.
Third, to plot regularly gridded data you do not need plot_trisurf, use plot_surface:
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
x=np.linspace(0,50,50)
y=np.linspace(0,50,50)
X, Y = np.meshgrid(x, y)
values = np.sqrt(X**2 + Y**2)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(x, y, values)
plt.show()
Look for examples: http://matplotlib.org/examples/mplot3d/surface3d_demo.html

Categories