Error When Trying to Create Function Grapher - python

I am trying to make a program using Python that allows the user to pick a function and graph it over specified values. I have this:
import matplotlib.pyplot as plt
import math
import numpy as np
from sympy import Symbol, Derivative, sin, sympify
from sympy.core.sympify import SympifyError
x = Symbol('x')
fx = sympify(input("What is your function? "))
x_min = float(input("Enter x minimum: "))
x_max = float(input("Enter x maximum: "))
x_values = np.linspace(x_min, x_max, 3)
y_values = fx.doit().subs({x:x_values})
plt.plot(x_values, y_values)
plt.show()
I input x**2 for the function, 0 for x_min, and 3 for x_max. The error I get is:
Traceback (most recent call last):
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/core/sympify.py", line 178, in sympify
expr = parse_expr(a, locals or {}, rational, convert_xor)
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/parsing/sympy_parser.py", line 163, in parse_expr
expr = eval(code, global_dict, local_dict) # take local objects in preference
File "<string>", line 1
[Float ('0.' )Float ('1.5' )Float ('3.' )]
^
SyntaxError: invalid syntax
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/joe126/Dropbox/Python/Chapter02.py", line 16, in <module>
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/core/basic.py", line 831, in subs
so, sn = sympify(o), sympify(n)
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/sympy/core/sympify.py", line 180, in sympify
raise SympifyError('could not parse %r' % a)
sympy.core.sympify.SympifyError: SympifyError: "could not parse '[0. 1.5 3. ]'"
What is going wrong? Thanks.

I cannot reproduce the error. I get the same error as Georgy: a shape mismatch when plotting. But why don't you try using lambdify to evaluate the function like this:
import matplotlib.pyplot as plt
import math
import numpy as np
from sympy import Symbol, Derivative, sin, sympify, lambdify
from sympy.core.sympify import SympifyError
x = Symbol('x')
fx = sympify(input("What is your function? "))
x_min = float(input("Enter x minimum: "))
x_max = float(input("Enter x maximum: "))
x_values = np.linspace(x_min, x_max, 3)
fx_lambda = lambdify(x,fx)
y_values = fx_lambda(x_values)
plt.plot(x_values, y_values)
plt.show()
Result for x**2 from 0 to 3

Related

Problem with plotting multiple functions with a for loop in matplotlib

I am using a for loop to plot a curve for each parameter-value (k) - this works just fine for all the negative k-values, but when the loop reaches the k values = 0 or greater, the lambdify function seems to collapse and I get an error stating the dimensions of x and y are not equal.
This is my code:
import sympy as sym
import numpy as np
import matplotlib.pyplot as plt
eta = np.logspace(-1,2,21) #defines eta values, 21 decades from 0.1 to 100
relrho = np.logspace(-2,2,25) #defines values of rho2/rho1, 25 values from 0.01 to 100
k = (relrho-1)/(relrho+1) #defines the reflection coefficient
#parameter of type curve is k
#rhoa/rho1 is the y-axis
#eta is the x-axis
#R is assigned as the ratio of rho_a to rho_1
#x is assigned to eta
#y is assigned to k
x = sym.symbols('x', real = True)
y = sym.symbols('y')
for y in k: #for-loop assumes k value before while-loop is run, then plots the curve, then new k value is assumed
n=1; R=1;
while n<=500:
Rnew = 2*x**3*y**n/(((2*n)**2+x**2)**(3/2))
R = R + Rnew
n = n + 1
R = sym.lambdify(x,R)
plt.loglog(eta, R(eta))
plt.show()
What is going wrong? I am completely at a dead end right now... clueless...
If I plot the curves individually I can plot them for any k-value just fine, but in the loop it collapses after 12 iterations.
runfile('C:/Users/aslak/OneDrive/Desktop/Typecurves.py', wdir='C:/Users/aslak/OneDrive/Desktop')
Traceback (most recent call last):
File "C:\Users\aslak\OneDrive\Desktop\Typecurves.py", line 44, in <module>
plt.loglog(eta, R(eta))
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\pyplot.py", line 2750, in loglog
return gca().loglog(*args, **kwargs)
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_axes.py", line 1868, in loglog
return self.plot(
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_axes.py", line 1743, in plot
lines = [*self._get_lines(*args, data=data, **kwargs)]
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 273, in __call__
yield from self._plot_args(this, kwargs)
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 399, in _plot_args
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (21,) and (1,)
runfile('C:/Users/aslak/OneDrive/Desktop/Typecurves.py', wdir='C:/Users/aslak/OneDrive/Desktop')
Traceback (most recent call last):
File "C:\Users\aslak\OneDrive\Desktop\Typecurves.py", line 34, in <module>
plt.loglog(eta, R(eta))
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\pyplot.py", line 2750, in loglog
return gca().loglog(*args, **kwargs)
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_axes.py", line 1868, in loglog
return self.plot(
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_axes.py", line 1743, in plot
lines = [*self._get_lines(*args, data=data, **kwargs)]
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 273, in __call__
yield from self._plot_args(this, kwargs)
File "C:\Users\aslak\anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 399, in _plot_args
raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (21,) and (1,)
The problem is that when y=0, then 2*x**3*y**n/(((2*n)**2+x**2)**(3/2)) will be 0, hence R will be zero. When you lambdify it and pass in a numpy array, it will return the scalar value 0. We need to take into account this fact. Note that in the following code block I also optimize for speed: only one symbolic addition will be executed for every iteration of the for loop.
import sympy as sym
import numpy as np
import matplotlib.pyplot as plt
eta = np.logspace(-1,2,21) #defines eta values, 21 decades from 0.1 to 100
relrho = np.logspace(-2,2,25) #defines values of rho2/rho1, 25 values from 0.01 to 100
k = (relrho-1)/(relrho+1) #defines the reflection coefficient
#parameter of type curve is k
#rhoa/rho1 is the y-axis
#eta is the x-axis
#R is assigned as the ratio of rho_a to rho_1
#x is assigned to eta
#y is assigned to k
x = sym.symbols('x', real = True)
y = sym.symbols('y')
for y in k: #for-loop assumes k value before while-loop is run, then plots the curve, then new k value is assumed
print("y", y)
n=1; R=1;
addends = []
while n<=500:
addends.append(2*x**3*y**n/(((2*n)**2+x**2)**(3/2)))
n = n + 1
R = Add(R, *addends)
R = sym.lambdify(x,R)
R_val = R(eta)
if not hasattr(R_val, "__iter__"):
R_val = R_val * np.ones_like(eta)
plt.loglog(eta, R_val)
plt.show()
Davide_sd pointed out why the code fails, but in this case it is faster to avoid sympy altogether:
import numpy as np
import matplotlib.pyplot as plt
eta = np.logspace(-1, 2, 21)
relrho = np.logspace(-2, 2, 25)
k = ((relrho - 1) / (relrho + 1))
n = np.r_[1:501]
y = k[None, :, None]
x = eta[:, None, None]
R = (2 * x**3 * y**n / (((2 * n)**2 + x**2)**(3 / 2))).sum(axis=2) + 1
plt.loglog(eta, R)
plt.show()

Python: plotting an exponential on an axis

I'm currently working on a piece of code to model the evolution of the dark energy equation of state parameter w with the scale factor a. In order to do this I am solving a system of three coupled ODEs, however the derivative used is with respect to e-foldings N = ln(a) (in the code x = w and ln(a) = t for simplicity). I have the following code:
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
import math
plt.rc('text', usetex=True)
plt.rc('font', family='serif')
def f(s,t):
p = 1.0
G = 1.0 + (1.0/p)
xm = 0
x = s[0]
y = s[1]
z = s[2]
dxdt = (x - 1.0)*(3.0*(1.0 + x) - z*math.sqrt(3.0*(1.0 + x)*y))
dydt = -3.0*(x - xm)*y*(1.0 - y)
dzdt = -math.sqrt(3.0*(1.0 + x)*y)*(G - 1.0)*(z**2)
return [dxdt, dydt, dzdt]
t = np.linspace(0.0001,1,10000)
s0 = [-0.667,0.01,0.45]
s = odeint(f,s0,t)
plt.plot(t,s[:,0],'b-')
plt.grid(True)
plt.xlabel('e-foldings, N = ln(a)')
plt.ylabel('Equation of state parameter w')
plt.show()
which gives me this plot.
This works fine, however I want the x-axis in units of a and not N = ln(a) but I can't figure out how to make it work. I've tried changing the plot line to plt.plot(math.exp(t),s[:,0],'b-') but I get the following error:
Traceback (most recent call last):
File "/Users/bradleyaldous/propr2.py", line 26, in <module>
plt.plot(math.exp(t),s[:,0],'b-')
TypeError: only size-1 arrays can be converted to Python scalars
[Finished in 6.0s]
Any help is greatly appreciated.
EDIT:
I've tried using np.exp() in the plot line like I did with the

ValueError shape <= 0 for distribution function

I need to complete a distribution function which looks like this into python:
−∞< x <∞,
P(x)dx= ((1+x^2/n)^-(n+1)/2) * Γ(n+1/2)/Γ(n/2)*(nπ)**1/2 dx, n=1.
So i tried it like this:
from numpy import *
from scipy import stats
from scipy.special import gammaln
from pylab import *
def studentstPDF(x,n=1):
"""
Call:
d = studentstPDF(x,n)
Input argument:
x: float (array)
n: float, default = 1.0
Output argument:
p: float
Examples:
In [1]: studentstPDF(1,1)
Out[1]: 0.1591549
"""
p = (1+((x**2)/n))**((-n+1)/2) * gamma((n+1)/2) / gamma(n/2) * (n*math.pi)**1/2
p[x<inf] = 0.0
p[x>-inf] = 0.0
return(p)
but now I get the error 'ValueError: shape <= 0'
What does that mean? And where am I wrong with my function?
In [16]:
studentstPDF(1,1)
Traceback (most recent call last):
File "<ipython-input-16-ddd6d9df823d>", line 1, in <module>
studentstPDF(1,1)
File "/Users/Veysel/Downloads/Exercise4-2/exercise4.py", line 122, in studentstPDF
p = (1+((x**2)/n))**((-n+1)/2) * gamma((n+1)/2) / gamma(n/2) * (n*math.pi)**1/2
File "mtrand.pyx", line 1871, in mtrand.RandomState.gamma (numpy/random/mtrand/mtrand.c:13491)
ValueError: shape <= 0
Your gamma function from scipy.special is most likely being overwritten by another gamma function of another nature, perhaps a random variable function from your mass imports. Import like this instead:
from scipy.special import gamma as Gamma
and write out your expression like this:
p = (1+((x**2)/n))**((-n+1)/2) * Gamma((n+1)/2) / Gamma(n/2) * (n*math.pi)**1/2
If you absolutely have to import the same way, use scipy.special.gamma in place of your current gamma calls and import scipy.
Your error itself is a result of attempting to use the multiplicative operator * on operands that do not have the same shape.

Division by zero ? (In newton iteration method)

I'm doing a newton iteration to find T_a. Everything seems fine in the code except in one the very first definitions.
My rho(T_a) returns a division by zero (it assumes that T_a is zero while it's just a variable. If I change the T_a in the equation to something like 100, everything runs smoothly.
Any idea why it's returning a division by zero?
from numpy import *
import numpy as np
import pylab
import scipy
from scipy.optimize import leastsq
from math import *
import matplotlib.pyplot as plt
from scipy import integrate
# THETA NOTATION:
#pi/2: substellar point
#-pi/2: antistellar point
#0: terminators
#define constants used in equations:
alb = 0.2 #constant albedo
F = 866 #J/s*m**2
R = 287.0 #J/K*kg
U = 5.0 #m/s
C_p = 1000 #J/K*kg
C_d = 0.0015
p1 = 10**4
p2 = 10**5.0
p3 = 10**6.0 #Pa
sig = 5.67*10**-8.0 #J/s*m**2*K**4 #Stefan-Boltzmann cst
def rho(T_a):
p1=10000.0
R=287.0 #J/K*kg
return (p1/(T_a*R))
def a(T_a):
U = 5 #m/s
C_p = 1000 #J/K*kg
C_d = 0.0015
return rho(T_a)*C_p*C_d*U
#################################################
##### PART 2 : check integrals equality
#################################################
#define the RHS and LHS of integral equality
def LHS(theta):
return (1-alb)*F*np.sin(theta)*np.cos(theta)
#define the result of each integral
Left = integrate.quad(lambda theta: LHS(theta), 0, pi/2)[0]
#define a function 1-(result LHS/result RHS) >>> We look for the zero of this
x0=130.0 #guess a value for T_a
#T_a = 131.0
#Python way of solving for the zero of the function
#Define T_g in function of T_a, have RHS(T_a) return T_g**4 etc, have result_RHS(T_a) return int.RHS(T_a),
#have func(T_a) return result_LHS/result_RHS
def T_g(T_a,theta):
return np.roots(array([(sig),0,0,(a(T_a)),((-a(T_a)*T_a)-LHS(theta))]))[3]
def RHS(theta,T_a):
return sig*T_g(T_a,theta)**4*np.cos(theta)
def result_RHS(T_a,theta):
return integrate.quad(lambda theta: RHS(T_a,theta), -pi/2, pi/2)[0]
def function(T_a,theta):
return 1-((Left/result_RHS(T_a,theta)))
theta = np.arange(-pi/2, pi/2, pi/20)
T_a_0 = scipy.optimize.newton(function,x0,fprime=None,args=(theta,),tol= (10**-5),maxiter=50000)
Output:
Traceback (most recent call last):
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 85, in <module>
T_a_0 = scipy.optimize.newton(function,x0,fprime=None,args=(theta,),tol=(10**-5),maxiter=50000)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/optimize/zeros.py", line 120, in newton
q0 = func(*((p0,) + args))
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 81, in function
return 1-((Left/result_RHS(T_a,theta)))
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 78, in result_RHS
return integrate.quad(lambda theta: RHS(T_a,theta), -pi/2, pi/2)[0]
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 247, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 312, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 78, in <lambda>
return integrate.quad(lambda theta: RHS(T_a,theta), -pi/2, pi/2)[0]
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 75, in RHS
return sig*T_g(T_a,theta)**4*np.cos(theta)
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 72, in T_g
return np.roots(array([(sig),0,0,(a(T_a)),((-a(T_a)*T_a)-LHS(theta))]))[3]
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 38, in a
return rho(T_a)*C_p*C_d*U
File "/Users/jadecheclair/Documents/PHY479Y/FindT_a.py", line 32, in rho
return (p1/(T_a*R))
ZeroDivisionError: float division by zero
Your RHS function is defined slightly differently to all the others, in that it has theta first and T_a as its second argument:
def RHS(theta,T_a):
return sig*T_g(T_a,theta)**4*np.cos(theta)
I think that's why you passed the arguments in the wrong order here:
lambda theta: RHS(T_a,theta)
Get them in the right order and you should be OK.
As a side-note, some of your imports look like they could cause weird bugs:
from numpy import *
from math import *
Numpy and the math module have at least a few function names in common, like sqrt. It's safer to just do import math and import numpy as np, and access the functions through the module name. Otherwise what happens when you call sqrt could change depending on the order you do your imports in.
You reversed your parameters:
In result_RHS you call: RHS(T_a,theta), but the parameter definition of RHS is def RHS(theta,T_a)
Swap those in in the definition and the error no longer occurs. Your definition should look like this:
def RHS(T_a, theta)

scipy curve_fit fails on exponential fit

When I try to do an exponential fit using curve_fit, scipy returns an error. Am I doing something wrong? Removing the negative sign from np.exp(-b * t) allows curve_fit to work, but the values it returns are way off.
#!/usr/bin/python
import numpy as np
import scipy as sp
from scipy.optimize import curve_fit
import scipy.optimize as opt
import matplotlib.pyplot as plt
x = [40,45,50,55,60]
y = [0.99358851674641158, 0.79779904306220106, 0.60200956937799055, 0.49521531100478472, 0.38842105263157894]
def model_func(t, a, b, c):
return a * np.exp(-b * t) + c
opt_parms, parm_cov = sp.optimize.curve_fit(model_func, x, y, maxfev=1000)
a,b,c = opt_parms
print a,b,c
print x
print y
print model_func(x, a,b,c)
Fails with error:
Traceback (most recent call last):
File "asdf.py", line 18, in <module>
opt_parms, parm_cov = sp.optimize.curve_fit(model_func, x, y, maxfev=1000)
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 426, in curve_fit
res = leastsq(func, p0, args=args, full_output=1, **kw)
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 276, in leastsq
m = _check_func('leastsq', 'func', func, x0, args, n)[0]
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 13, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 346, in _general_function
return function(xdata, *params) - ydata
ValueError: operands could not be broadcast together with shapes (0) (5)
change x and y to numpy arrays
x = np.array([40,45,50,55,60])
y = np.array([0.99358851674641158, 0.79779904306220106, 0.60200956937799055, 0.49521531100478472, 0.38842105263157894])
then I think you are good, because the function requires vectorized computation, whereas lists are not adequate.

Categories