I am trying to make a polar plot of 1/t. What I have so far is below (which may be wrong). How can I finish this or make it work?
from pylab import *
import matplotlib.pyplot as plt
theta = arange(0, 6 * pi, 0.01)
def f(theta):
return 1 / theta
I think the problem is that your first value of f(theta) is 1/0 = inf
theta = np.arange(0, 6*np.pi, .01)[1:]
def f(x):
return 1/x
plt.polar(theta, f(theta))
and it looks even nicer if you zoom in:
from mpl_toolkits.axes_grid.axislines import SubplotZero
from matplotlib.ticker import MultipleLocator, FuncFormatter
import matplotlib.pyplot as plt
import numpy as np
plt.ion()
fig = plt.figure(1)
ax = SubplotZero(fig, 111)
fig.add_subplot(ax)
for dir in ax.axis:
ax.axis[dir].set_visible(dir.endswith("zero"))
ax.set_xlim(-.35,.4)
ax.set_ylim(-.25,.45)
ax.set_aspect('equal')
tick_format = lambda x, i: '' if x == 0.0 else '%.1f' % x
for a in [ax.xaxis, ax.yaxis]:
a.set_minor_locator(MultipleLocator(0.02))
a.set_major_formatter(FuncFormatter(tick_format))
theta = np.arange(2*np.pi/3,6*np.pi,0.01)
r = 1 / theta
ax.plot(r*np.cos(theta), r*np.sin(theta), lw=2)
plt.show()
raw_input()
If you want a square plot like Mathematica gave you, the standard plot function just takes an array of x values and an array of y values. Here, f(theta) is the radius, and cos and sin give the x and y directions, so
plt.plot(f(theta)*cos(theta), f(theta)*sin(theta))
should do the job. This will show all of the data, rather than a cleverly chosen subset like in Mathematica, so you might want to limit it. For example:
plt.xlim((-0.35,0.43))
plt.ylim((-0.23,0.45))
gives me the ranges in your version.
Related
I have an implicit function, say x**2 - y = 0 (to simplify), of which I want to obtain a plot for a certain range of x values.
sympy.plot_implicit usually gives some spreading of the lines that I am not happy with.
I would like to have access to the plotted values, and so pyplot.plot is preferable to me. Usually I use the following piece of code to get my explicit Sympy functions plotted, but I am unsure how to use something similar for exp = sym.Eq(x**2 - y, 0). Does anyone have a solutions for this?
import sympy as sym
import numpy as np
from matplotlib import pyplot as plt
x, y = sym.symbols('x y', nonnegative=True)
exp = x**2
# Plot using a numpy-ready function
x_arr = np.linspace(-2, 2, 100)
exp_func = sym.lambdify(x, exp, 'numpy')
exp_arr = exp_func(x_arr)
plt.plot(x_arr, exp_arr)
PS: my real expression is b_sim (see below) and I want the plot for the equation b_sim = -1. With sym.plot_implicit(b_sim + 1, (n,0.225,1.5), (h, -1.1, 1.1)) one can see the lines spreading I dislike. Following Oscar Benjami's tips here, I attempted the following piece of code that is giving an error for roots.
from sympy import *
h, nu = symbols('h nu', nonnegative=True)
b_sim = 1.0*cos(pi*sqrt(1 - h)/(2*nu))*cos(pi*sqrt(h + 1)/(2*nu)) - 1.0*sin(pi*sqrt(1 - h)/(2*nu))*sin(pi*sqrt(h + 1)/(2*nu))/sqrt(1 - h**2)
eq = Eq(b_sim + 1, 0)
sols = roots(eq, h)
sym.plot(*sols, (nu, 0.225, 1.5), ylim=(-1.1, 1.1))
The line spread of plot_implicit is caused by the adaptive algorithm. If you set the option adaptive=False the plotting module would use a meshgrid approach. However, due to the implementation, the figure is likely not going to be good (too much "segmentation").
This is how you can do it with Numpy and Matplotlib:
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
import numpy as np
expr = eq.rewrite(Add)
f = lambdify([nu, h], expr)
n = 2000j
nnu, hh = np.mgrid[0.225:1.5:n, -1.1:1.1:n]
res = f(nnu, hh)
plt.figure()
cmap = ListedColormap(["tab:blue", "tab:blue"])
plt.contour(nnu, hh, res, levels=[0], cmap=cmap)
plt.show()
To have access to the plotted values of a sympy function plot, in this case the coordinates of lines2d plot, is simple.
Here is the code that plots the function.
import matplotlib.pyplot as plt
from sympy import symbols
import numpy as np
import sympy
x, y = symbols('x y', nonnegative=True)
exp = x**2
# Plot using a numpy-ready function
x_arr = np.linspace(-2, 2, 10) #small number for demo
exp_func = sympy.lambdify(x, exp, 'numpy')
exp_arr = exp_func(x_arr)
plt.figure(figsize=(4, 3))
lines2d = plt.plot(x_arr, exp_arr)
In the code above, lines2d is a list of line2d objects. To get the coordinates from the 1st (only one in this case), do this:
xys = lines2d[0].get_xydata()
And you can use it to plot with this code:-
fig = plt.figure(figsize=(4, 3))
ax = fig.add_subplot()
ax.plot(xys[:,0], xys[:,1])
I draw an exponential chart and now I want to move the peak freely along the X axis.
The center should be like a bell, and the right side like a my current chart but totaly reversed.
How can I do that?
import matplotlib
import math
import numpy as np
matplotlib.use('Agg')
import matplotlib.pyplot as plt
arr_name=[]
arr_value=[]
k=-0.01
for l in range(0,100):
x=pow(k,2)*np.exp(-k*1.8);
if (l%10)==0:
arr_name.append(l/10)
else:
arr_name.append("")
arr_value.append(x)
k=k+0.05
print x
y_pos = np.arange(len(arr_name))
plt.figure(figsize=(8,4))
plt.rcParams.update({'font.size': 8})
plt.subplot(1,1,1)
plt.plot(y_pos, arr_value, '-r')
plt.xticks(y_pos, arr_name)
plt.savefig('/var/www/html/bar/img/test_chart.png')
update:
possible solution to draw peak at the center of the chart:
for l in range(0,100):
x=pow(k,5)*np.exp(-k*1.96);
if (l%10)==0:
arr_name.append(l/10)
else:
arr_name.append("")
arr_value.append(x)
if l>50:
k=k-0.05
else:
k=k+0.05
print x
adding reversibility:
arr_value.reverse()
You can plot this much easier without a four loop. Varying the coefficient inside the exponential moves the value and location of the peak.
import matplotlib.pyplot as plt
import numpy as np
def f(x, s):
x**2 * np.exp(-s*x)
x = np.linspace(0, 10, 100)
y1 = f(x, 1.8)
y2 = f(x, 0.8)
plt.plot(x, y1, label='s=1.8')
plt.plot(x, y2, label='s=0.8')
plt.legend()
plt.show()
I have numerically solved the Lorenz equations using SciPy with the script:
# Lorenz Equations SciPy solver
import numpy as np
from scipy import integrate
from math import cos
from matplotlib import pyplot as plt
a, b = 0, 100
sigma, rho, beta = 10, 28, 8/3
N = 1000000
h = (b-a) / float(N)
def solvr(Y, t):
return [sigma*(Y[1]-Y[0]), Y[0]*(rho-Y[2])-Y[1], Y[0]*Y[1]-beta*Y[2]]
t = np.arange(a, b, h)
asol = integrate.odeint(solvr, [0, 1, 1], t)
x = asol[:,0]
y = asol[:,1]
z = asol[:,2]
Now what I would like to do is plot x, y and z (which are all Numpy ndarrays, if you are unsure) against each other in a 3D line (or wireframe) plot. I think this would have to be done using matplotlib, but I am not picky, so long as you give me a solution that will plot the data in 3D I do not care what modules I need to import.
Here is the Lorenz attractor both in 3D and animated. The script is in the following link (along with many goodies) in Jake VanderPlas' Pythonic Perambulations. You can learn a lot by going line-by-line through the script - it's an elegant use of matplotlib objects.
https://jakevdp.github.io/blog/2013/02/16/animating-the-lorentz-system-in-3d/
I added these two lines just before return in the animate function, and then used ImageJ to import the "image stack" and save the "animated GIF":
fname = "Astro_Jake_" + str(i+10000)[1:]
fig.savefig(fname)
Note: For OSX it seems to be necessary to set blit = False in animation.FuncAnimation.
Here is a minimal, simplified example of plotting lines in 3D based on the above:
def lorentz_deriv((x, y, z), t0, sigma=10., beta=8./3, rho=28.0):
"""Compute the time-derivative of a Lorentz system."""
return [sigma * (y - x), x * (rho - z) - y, x * y - beta * z]
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.integrate import odeint as ODEint
x = np.linspace(0, 20, 1000)
y, z = 10.*np.cos(x), 10.*np.sin(x) # something simple
fig = plt.figure()
ax = fig.add_subplot(1,2,1,projection='3d')
ax.plot(x, y, z)
# now Lorentz
times = np.linspace(0, 4, 1000)
start_pts = 30. - 15.*np.random.random((20,3)) # 20 random xyz starting values
trajectories = []
for start_pt in start_pts:
trajectory = ODEint(lorentz_deriv, start_pt, times)
trajectories.append(trajectory)
ax = fig.add_subplot(1,2,2,projection='3d')
for trajectory in trajectories:
x, y, z = trajectory.T # transpose and unpack
# x, y, z = zip(*trajectory) # this also works!
ax.plot(x, y, z)
plt.show()
There is a brief example / tutorial on how to do wireframe plots (as well as 3d scatter) at the matplotlib site http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#wireframe-plots
The following formula is used to classify points from a 2-dimensional space:
f(x1,x2) = np.sign(x1^2+x2^2-.6)
All points are in space X = [-1,1] x [-1,1] with a uniform probability of picking each x.
Now I would like to visualize the circle that equals:
0 = x1^2+x2^2-.6
The values of x1 should be on the x-axis and values of x2 on the y-axis.
It must be possible but I have difficulty transforming the equation to a plot.
You can use a contour plot, as follows (based on the examples at http://matplotlib.org/examples/pylab_examples/contour_demo.html):
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1.0, 1.0, 100)
y = np.linspace(-1.0, 1.0, 100)
X, Y = np.meshgrid(x,y)
F = X**2 + Y**2 - 0.6
plt.contour(X,Y,F,[0])
plt.show()
This yields the following graph
Lastly, some general statements:
x^2 does not mean what you think it does in python, you have to use x**2.
x1 and x2 are terribly misleading (to me), especially if you state that x2 has to be on the y-axis.
(Thanks to Dux) You can add plt.gca().set_aspect('equal') to make the figure actually look circular, by making the axis equal.
The solution of #BasJansen certainly gets you there, it's either very inefficient (if you use many grid points) or inaccurate (if you use only few grid points).
You can easily draw the circle directly. Given 0 = x1**2 + x**2 - 0.6 it follows that x2 = sqrt(0.6 - x1**2) (as Dux stated).
But what you really want to do is to transform your cartesian coordinates to polar ones.
x1 = r*cos(theta)
x2 = r*sin(theta)
if you use these substitions in the circle equation you will see that r=sqrt(0.6).
So now you can use that for your plot:
import numpy as np
import matplotlib.pyplot as plt
# theta goes from 0 to 2pi
theta = np.linspace(0, 2*np.pi, 100)
# the radius of the circle
r = np.sqrt(0.6)
# compute x1 and x2
x1 = r*np.cos(theta)
x2 = r*np.sin(theta)
# create the figure
fig, ax = plt.subplots(1)
ax.plot(x1, x2)
ax.set_aspect(1)
plt.show()
Result:
How about drawing x-values and calculating the corresponding y-values?
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-1, 1, 100, endpoint=True)
y = np.sqrt(-x**2. + 0.6)
plt.plot(x, y)
plt.plot(x, -y)
produces
This can obviously be made much nicer, but this is only for demonstration...
# x**2 + y**2 = r**2
r = 6
x = np.linspace(-r,r,1000)
y = np.sqrt(-x**2+r**2)
plt.plot(x, y,'b')
plt.plot(x,-y,'b')
plt.gca().set_aspect('equal')
plt.show()
produces:
Plotting a circle using complex numbers
The idea: multiplying a point by complex exponential () rotates the point on a circle
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
num_pts=20 # number of points on the circle
ps = np.arange(num_pts+1)
# j = np.sqrt(-1)
pts = np.exp(2j*np.pi/num_pts *(ps))
fig, ax = plt.subplots(1)
ax.plot(pts.real, pts.imag , '-o')
ax.set_aspect(1)
plt.show()
Today I decided to write simple program in Python, just to practice before exam. Firstly, I wanted to draw sin and cos plot, which wasn't so hard. But then, I decided to challenge myself and draw tangent plot.
import pylab as p
x= p.arange(-1.0,1.0,0.1)
y= (p.sin(2*p.pi*x)) / (p.cos(2*p.pi*x))
p.plot(x,y,'g-',lw=1)
p.show()
It returns... ugh... this:
As you can see, it looks more like ECK plot than tangent plot. Does anyone knows what's wrong?
If you increase the number of points in x,
import pylab as p
import numpy as np
x = p.linspace(-1.0, 1.0, 1000)
y = (p.sin(2 * p.pi * x)) / (p.cos(2 * p.pi * x))
p.plot(x, y, 'g-', lw=1)
p.show()
you get something like this:
Notice how large the y-range is getting. Matplotlib is not able to show you much of the small values in the tangent curve because the range is so large.
The plot can be improved by ignoring the extremely large values near the asymptotes. Using Paul's workaround to handle asymptotes,
import pylab as p
import numpy as np
x = p.linspace(-1.0, 1.0, 1000)
y = (p.sin(2 * p.pi * x)) / (p.cos(2 * p.pi * x))
tol = 10
y[y > tol] = np.nan
y[y < -tol] = np.nan
p.plot(x, y, 'g-', lw=1)
p.show()
you get
import pylab as p
x= p.arange(-1.0,1.0,0.01) # <- 0.01 step size.
y= (p.sin(2*p.pi*x)) / (p.cos(2*p.pi*x))
# y = p.tan(2*p.pi*x)
p.plot(x,y,'g-',lw=1)
p.ylim([-4, 4]) # <- Restricting the ylim so we don't see the ~inf values.
p.show()
This will be the result if you don't set ylim. (the values approach infinity)
Result with setting ylim.