Plot/Convert an expression coming from sympy: Taylor series with matplotlib - python

iยดam trying to plot the function sin(x)/x and a taylor approximation of it.
i use python 3 and pyzo - the first plot works but i have problems converting the series coming from the sympy module to an numpy expression that would work.
import numpy as np
import matplotlib.pyplot as plt
import sympy as sp
from sympy.abc import x
x = np.linspace(-10, 10, 100)
y = np.sin(x)/x #first function
plt.plot(x, y, 'k') #this is working fine
### this is a code that removes the "0(x**something)" part of
the series at the end
i found it here http://pastebin.com/ZNQakWP7
def series(expr, x, x0, n, removeO=False):
"""
sympy bugs avoided
"""
# expr_series = expr.series(x, x0, n)
# return expr_series.removeO() if removeO else expr_series
expansion = list()
for t in expr.lseries(x, x0):
p = t.as_coeff_exponent(x)[1]
if p < n:
expansion.append(t)
else:
break
if not removeO:
expansion.append(sp.O(x**n))
return sp.Add(*expansion)
### my code continued ####
y_t=series(sp.sin(x)/x,x,0,6,removeO=True)
if i look at y_t now i get this approximation
out: x**4/120 - x**2/6 + 1
Now i try to convert this to numpy in order to plot it as i did with the first function.
f_t = lambdify(x, y_t,modules=['numpy'])
x = np.linspace(-10, 10, 100) #i do this because x has
#been a symbolic variable before
plt.plot(x, y_t, 'b') #this is where the problem occurs
i get the first plot also a second error message:
File "<console>", line 1, in <module>
File "F:\pyzo2013_0_2_2\lib\site-packages\matplotlib\pyplot.py", line 2832, in plot
ret = ax.plot(*args, **kwargs)
File "F:\pyzo2013_0_2_2\lib\site-packages\matplotlib\axes.py", line 3998, in plot
for line in self._get_lines(*args, **kwargs):
How can i achieve my idea to plot something coming from sympy?
Another idea i had was to convert the sympy out from the series to a string and then parsing this somehow to a numpy expression. I would be thankful for any help here!

I think your problem is that this:
plt.plot(x, y_t, 'b') #this is where the problem occurs
should be something like:
plt.plot(x, f_t(x), 'b')
f_t is the lambdified series, so it is a callable function that evaluates its argument.
I used lambdify in the following example, and it works for me:
from sympy.abc import x
from sympy import sin, series
from sympy.utilities.lambdify import lambdify
import numpy as np
import matplotlib.pyplot as plt
func = sin(x)/x
taylor = series(func, n=6).removeO()
evalfunc = lambdify(x, func, modules=['numpy'])
evaltaylor = lambdify(x, taylor, modules=['numpy'])
t = np.linspace(-5.5, 5.5, 100)
plt.plot(t, evalfunc(t), 'b', label='sin(x)/x')
plt.plot(t, evaltaylor(t), 'r', label='Taylor')
plt.legend(loc='best')
plt.show()
Here's the plot generated by the script.

Related

Plotting Taylor series expansions from Sympy in MatPlotLib [duplicate]

iยดam trying to plot the function sin(x)/x and a taylor approximation of it.
i use python 3 and pyzo - the first plot works but i have problems converting the series coming from the sympy module to an numpy expression that would work.
import numpy as np
import matplotlib.pyplot as plt
import sympy as sp
from sympy.abc import x
x = np.linspace(-10, 10, 100)
y = np.sin(x)/x #first function
plt.plot(x, y, 'k') #this is working fine
### this is a code that removes the "0(x**something)" part of
the series at the end
i found it here http://pastebin.com/ZNQakWP7
def series(expr, x, x0, n, removeO=False):
"""
sympy bugs avoided
"""
# expr_series = expr.series(x, x0, n)
# return expr_series.removeO() if removeO else expr_series
expansion = list()
for t in expr.lseries(x, x0):
p = t.as_coeff_exponent(x)[1]
if p < n:
expansion.append(t)
else:
break
if not removeO:
expansion.append(sp.O(x**n))
return sp.Add(*expansion)
### my code continued ####
y_t=series(sp.sin(x)/x,x,0,6,removeO=True)
if i look at y_t now i get this approximation
out: x**4/120 - x**2/6 + 1
Now i try to convert this to numpy in order to plot it as i did with the first function.
f_t = lambdify(x, y_t,modules=['numpy'])
x = np.linspace(-10, 10, 100) #i do this because x has
#been a symbolic variable before
plt.plot(x, y_t, 'b') #this is where the problem occurs
i get the first plot also a second error message:
File "<console>", line 1, in <module>
File "F:\pyzo2013_0_2_2\lib\site-packages\matplotlib\pyplot.py", line 2832, in plot
ret = ax.plot(*args, **kwargs)
File "F:\pyzo2013_0_2_2\lib\site-packages\matplotlib\axes.py", line 3998, in plot
for line in self._get_lines(*args, **kwargs):
How can i achieve my idea to plot something coming from sympy?
Another idea i had was to convert the sympy out from the series to a string and then parsing this somehow to a numpy expression. I would be thankful for any help here!
I think your problem is that this:
plt.plot(x, y_t, 'b') #this is where the problem occurs
should be something like:
plt.plot(x, f_t(x), 'b')
f_t is the lambdified series, so it is a callable function that evaluates its argument.
I used lambdify in the following example, and it works for me:
from sympy.abc import x
from sympy import sin, series
from sympy.utilities.lambdify import lambdify
import numpy as np
import matplotlib.pyplot as plt
func = sin(x)/x
taylor = series(func, n=6).removeO()
evalfunc = lambdify(x, func, modules=['numpy'])
evaltaylor = lambdify(x, taylor, modules=['numpy'])
t = np.linspace(-5.5, 5.5, 100)
plt.plot(t, evalfunc(t), 'b', label='sin(x)/x')
plt.plot(t, evaltaylor(t), 'r', label='Taylor')
plt.legend(loc='best')
plt.show()
Here's the plot generated by the script.

Plotting a function with more than one variable in Matplotlib

import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
from ipywidgets.widgets import interact
sym.init_printing(use_latex="mathjax")
x, y, z, t = sym.symbols('x y z t')
We were given a function in class to write as code
\begin{equation}
p_w(z,t)=\frac{1}{\sqrt{\pi \left(1-\exp\left[-2 t\right]\right)}}
\exp\left[-\frac{\left(z-\exp\left[-t\right]\right)^{2}}{1-
\exp\left[-2t\right]}\right]
\end{equation}
which I have written as this
p_w = (1/(sym.sqrt((sym.pi)*(1-(sym.exp(-2*t))))))*(sym.exp((-(z-sym.exp(-t))**2)/(1-sym.exp(-2*t))))
Then find the partial differential equation
โˆ‚๐‘ก๐‘๐‘ค(๐‘ง,๐‘ก)=โˆ‚๐‘ง[๐‘ง๐‘๐‘ค(๐‘ง,๐‘ก)]+1/2 โˆ‚2๐‘ง๐‘๐‘ค(๐‘ง,๐‘ก)
which I have written as this:
LHS=sym.diff(p_w,t,1)
#differentiate once with respect to t
RHS=sym.diff(z*p_w,z,1)+((1/2)*(sym.diff(p_w,z,2)))
#now differentiate with respect to z
Now we need to plot it and can only use matplotlib/numpy/sympy libraries.
Plot ๐‘๐‘ค(๐‘ง,๐‘ก) for the three values t=0.1,1,10 in a ๐‘๐‘ค(๐‘ง,๐‘ก) versus z diagram.
Here's what I've got so far:
t_points=[0.1,1,10]
#pw = sym.lambdify(t,p_w)
mytspace=np.linspace(0,10,200)
#myzspace=pw(mytspace)
plt.xlabel("t axis")
plt.ylabel("z axis")
plt.plot(t_array,np.zeros(3),'bs')
I haven't studied multivariable calculus before so I'm a bit lost!
Since one of your variables is given (you know t must be t=0.1, t=1 or t=10) your only variable for plotting is z. I know you are using sympy for the calculations, but for plotting maybe it's simpler to just return p_w as a numpy array. You can define a function to return p_w as so:
import numpy as np
import matplotlib.pyplot as plt
def p_w(z, t):
p_w = (1/(np.sqrt((np.pi)*(1-(np.exp(-2*t))))))*(np.exp((-(z-np.exp(-t))**2)/(1-np.exp(-2*t))))
return p_w
This will give you a numpy array with the results of p_w(z, t) where z is an array and t is just one number. Then you can just iterate over the values of t that you need:
t_points=[0.1, 1, 10]
z = np.linspace(0,10,200)
for t in t_points:
plt.plot(z, p_w(z, t), label='t = {0}'.format(t))
plt.legend()
plt.show()
Result:

How do I use scipy and matplotlib to fit a reverse sigmoid function

I have some data points which I was successfully able to graph, but now I would like to fit a curve to the data. I looked into other stackoverflow answers and found a few questions, but I can't seem to implement them. I know the function is a reverse sigmoid.
I would like to use this hill equation: https://imgur.com/rYqEASm
So far I tried to use the curve_fit() function from the scipy package to find the parameters but my code always breaks.
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
x = np.array([1, 1.90, 7.70, 30.10, 120.40, 481.60, 1925.00, 7700.00])
y = np.array([4118.47, 4305.79, 4337.47, 4838.11, 2660.76, 1365.05, 79.21, -16.40])
def fit_hill(t,b,s,i,h):
return b + ((t-b)/(1 + (((x * s)/i)**-h)))
plt.plot(x,y, 'o')
plt.xscale('log')
plt.show()
params = curve_fit(fit_hill, x, y)
[t,b,s,i,h] = params[0]
fit_hill should have 6 parameters.
(see https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html)
fit_hill(x,t,b,s,i,h).
You should try to give an initial guess for parameters.
For example in your model, when x=0, the value is t. So you can set the value at x=0 as an estimate for t.
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
x = np.array([1, 1.90, 7.70, 30.10, 120.40, 481.60, 1925.00])
y = np.array([4118.47, 4305.79, 4337.47, 4838.11, 2660.76, 1365.05, 79.21])
def fit_hill(x,t,b,s,i,h):
return b + ((t-b)/(1 + (((x * s)/i)**-h)))
plt.plot(x,y, 'o')
popt,pcov = curve_fit(fit_hill, x, y,(4118,200,1,1900,-2))
plt.plot(x,fit_hill(x,*popt),'+')
plt.xscale('log')
plt.show()
Have you drawn your model to visualize if it is suitable for you data ?
s and i, used only in s/i could be replaced with one variable in your model.

Plotting a 3D quiver plot and ode

I am trying to do a 3D quiver plot and combining it with odeint to solve a linearized equation. Basically, I want something similar to this but in 3D. The particular issue I am having is that near the end of the code, when I am doing the ax.quiver() plot, I keep getting the error that "val must be a float or nonzero sequence of floats", and I am unsure how to resolve it.
from scipy.integrate import odeint
from numpy import *
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
fig = plt.figure()
ax =fig.add_subplot(1, 1, 1, projection='3d')
ax.set_xlabel('x')
ax.set_ylabel('u')
ax.set_zlabel('u1')
def testplot(X, t=0,c=0.2):
x = X[0]
u = X[1]
u1=X[2]
dxdt =x**2*(-1+x+u)*(1-x+(-1+c)*u**2)
du1dt =c**2*u*(2+x*(-4+2.25*x)+(-4 + 4*x)*u**2 + 2*u**4 + x**2*u*u1)
dudt=u1*dxdt
return [dxdt, dudt,du1dt]
X0 = [0.01,0.995,-0.01]#initial values
t = linspace(0, 50, 250)
c=[0.2,0.5,1,2]#changing parameter
for m in c:
sol = odeint(testplot,X0,t,mxstep=5000000,args=(m,))#solve ode
ax.plot(sol[:,0],sol[:,1],sol[:,2],lw=1.5,label=r'$c=%.1f$'%m)
x = linspace(-3,3,15)
y = linspace(-4,4,15)
z= linspace(-2,2,15)
x,y,z = meshgrid(x,y,z) #create grid
X,Y,Z = testplot([x,y,z])
M = sqrt(X**2+Y**2+Z**2)#magnitude
M[M==0]=1.
X,Y,Z = X/M, Y/M, Z/M
ax.quiver(x,y,z,X,Y,Z,M,cmap=plt.cm.jet)
ax.minorticks_on()
ax.legend(handletextpad=0,loc='upper left')
setp(ax.get_legend().get_texts(),fontsize=12)
fig.savefig("testplot.svg",bbox_inches="tight",\
pad_inches=.15)
Looks like you have an extra argument in ax.quiver(). From what I can tell, it looks like "M" is the extra argument. Taking that out, your quiver call looks like:
ax.quiver(x,y,z,X,Y,Z,cmap=plt.cm.jet)
The resulting image looks like:

Algorithm equalivence from Matlab to Python

I've plotted a 3-d mesh in Matlab by below little m-file:
[x,n] = meshgrid(0:0.1:20, 1:1:100);
mu = 0;
sigma = sqrt(2)./n;
f = normcdf(x,mu,sigma);
mesh(x,n,f);
I am going to acquire the same result by utilization of Python and its corresponding modules, by below code snippet:
import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt
sigma = 1
def integrand(x, n):
return (n/(2*sigma*np.sqrt(np.pi)))*np.exp(-(n**2*x**2)/(4*sigma**2))
tt = np.linspace(0, 20, 2000)
nn = np.linspace(1, 100, 100)
T = np.zeros([len(tt), len(nn)])
for i,t in enumerate(tt):
for j,n in enumerate(nn):
T[i, j], _ = quad(integrand, -np.inf, t, args=(n,))
x, y = np.mgrid[0:20:0.01, 1:101:1]
plt.pcolormesh(x, y, T)
plt.show()
But the output of the Python is is considerably different with the Matlab one, and as a matter of fact is unacceptable.
I am afraid of wrong utilization of the functions just like linespace, enumerate or mgrid...
Does somebody have any idea about?!...
PS. Unfortunately, I couldn't insert the output plots within this thread...!
Best
..............................
Edit: I changed the linespace and mgrid intervals and replaced plot_surface method... The output is 3d now with the suitable accuracy and smoothness...
From what I see the equivalent solution would be:
import numpy as np
from scipy.stats import norm
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
x, n = np.mgrid[0:20:0.01, 1:100:1]
mu = 0
sigma = np.sqrt(2)/n
f = norm.cdf(x, mu, sigma)
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot_surface(x, n, f, rstride=x.shape[0]//20, cstride=x.shape[1]//20, alpha=0.3)
plt.show()
Unfortunately 3D plotting with matplotlib is not as straight forward as with matlab.
Here is the plot from this code:
Your Matlab code generate 201 points through x:
[x,n] = meshgrid(0:0.1:20, 1:1:100);
While your Python code generate only 20 points:
tt = np.linspace(0, 19, 20)
Maybe it's causing accuracy problems?
Try this code:
tt = np.linspace(0, 20, 201)
The seminal points to resolve the problem was:
1- Necessity of the equivalence regarding the provided dimensions of the linespace and mgrid functions...
2- Utilization of a mesh with more density to make a bee line into a high degree of smoothness...
3- Application of a 3d plotter function, like plot_surf...
The current code is totally valid...

Categories