Define and plot constant function in python - python

I am trying to plot a constant function in python (this is not what I am actually trying to do but if I solve this it might be a first step).
import matplotlib.pyplot as plt
import numpy as np
def constant_function(x):
return 2
t1 = np.arange(0.0,1.0,0.1)
plt.plot(t1,constant_function(t1))
However I get the error
ValueError: x and y must have same first dimension, but have shapes (10,) and (1,)

One option is to vectorize your function:
import matplotlib.pyplot as plt
import numpy as np
#np.vectorize
def constant_function(x):
return 2
t1 = np.arange(0.0, 1.0, 0.1)
plt.plot(t1, constant_function(t1))
plt.show()
this way constant_function(t1) will return [2 2 2 2 2 2 2 2 2 2] (i.e. [f(x[0]), f(x[1]), f(x[2]), ...]) instead of just 2 and the dimensions will match.

In my opinion vectorize is overkill to plot a simple "function" which just yields a constant value, especially if basic python syntax is the source of the problem. (And imho decorators are quite more advanced than using simple numpy methods.)
Instead I'd recommend just setting the return value of the function to an array of the same shape:
import matplotlib.pyplot as plt
import numpy as np
def constant_function(x):
return 2
t1 = np.arange(0.0,1.0,0.1)
plt.plot(t1, np.full(t1.shape, constant_function(t1)))
Since constant_function currently takes an argument which is not used, another improvement could be to construct the array inside constant_function, using the information from the argument x:
def constant_function(x):
return np.full(x.shape, 2)
t1 = np.arange(0.0,1.0,0.1)
plt.plot(t1, constant_function(t1))

Related

Error trying to plot a simple function in python

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
I get a different error depending on the integration method. The function works correctly when given a single value.
import matplotlib.pyplot as plt
import scipy as sp
import numpy as np
def mass_enc(R):
def int(r): return r**2 * r
return sp.integrate.quad(int, 0, R)
print(mass_enc(10))
t1 = np.arange(0.1, 5.0, 0.1)
plt.plot(t1, mass_enc(t1))
The problem is that you are calling sp.integrate.quad with an array as argument. While some functions actually allow that, quad does not. So you need to provide each value of R individually. This can be done by map(function, iterable). So here is how you can do it.
import matplotlib.pyplot as plt
import scipy as sp
import numpy as np
def inte(r):
return r**2 * r
def mass_enc(R):
return sp.integrate.quad(inte, 0, R)[0]
print(mass_enc(10))
t1 = np.arange(0.1, 5.0, 0.1)
m = map( mass_enc, t1)
plt.plot(t1, m)
plt.show()
Mind, that you should never call any object in python int, since int is a basic type in python and doing that can cause a lot of trouble.

Gradient of Sin(x)^4 is not same when calculated from its derivative

When I calculate and plot the derivative of Sin(x)^4 by directly putting the derivative of it which is 4 Sin(x)^3 Cos(x) for x= [0 to 180 deg] using the following code I get the right result.
import numpy as np
import matplotlib.pyplot as plt
a = np.power( np.sin( np.deg2rad(range(0,180)) ),4 )
c = 4 * np.sin( np.deg2rad(range(0,180) ))**3 * np.cos(np.deg2rad(range(0,180)))
plt.plot(a)
plt.plot(c)
plt.show()
But when I try to do the same thing with the numpy Gradient function then it gives me a different result i.e. the gradient is simply like straight line. For example, using the following code:
import matplotlib.pyplot as plt
a = np.power( np.sin( np.deg2rad(range(0,180)) ),4 )
plt.plot(a)
plt.plot(np.gradient(a))
plt.show()
I am still unable the understand the reason of the difference. Could any one please give me a clue why they are different ?
Actually in simulation work I have set of values in an array and I need to calculate the derivative of them over phi=range(0,180).
You are not correctly specifying the spacing between samples (which defaults to 1), so the answer you have is incorrectly scaled.
Try:
a = np.power(np.sin(np.deg2rad(range(0,180))),4 )
plt.plot(a)
plt.plot(np.gradient(a, np.deg2rad(1)))
Now c and np.gradient(a, np.deg2rad(1)) should be almost identical.

Optimising two arrays simultaneously with scipy optimize

I have a function that takes two m-dimensional arrays does some calculation with them (here it is very simplified) and returns one dimensional array. Also I have m-dimensional measurement data and would like to optimise those two arrays to fit the measurements. This worked fine with one arrays. I can just simply not get it to work with two arrays (or more). it always throws:
TypeError: Improper input: N=40 must not exceed M=20
Here is my Code. Thank you very much if anyone can help!
import numpy as np
from scipy import optimize
data=[np.arange(0,20.0,1),np.array([-52.368, 32.221, 40.102, 48.088, 73.106, 50.807, 52.235, 76.933, 65.737, 34.772, 94.376, 123.366, 92.71, 72.25, 165.051, 91.501, 118.92, 100.936, 56.747, 159.034])]
def line(m,b):
return m*b
guessm = np.ones(20) #initial guessed values for m
guessb = np.ones(20) #initial guesses values for b
guess = np.append(guessm,guessb)
errfunc= lambda p,y: (y-line(p[:20],p[20:]))
parameter, sucess = optimize.leastsq(errfunc, guess, args=(data[1]))
print(parameter)
plt.plot(data[0],d[1],'o')
plt.plot(data[0],line(parameter[0],parameter[1]))
plt.show()
If you want to fit a line, you should give the slope and intercept - two parameters, not 40. I suspect this is what you try to do:
import matplotlib.pyplot as plt
import numpy as np
from scipy import optimize
data=[np.arange(0,20.0,1),np.array([-52.368, 32.221, 40.102, 48.088, 73.106, 50.807, 52.235, 76.933, 65.737, 34.772, 94.376, 123.366, 92.71, 72.25, 165.051, 91.501, 118.92, 100.936, 56.747, 159.034])]
def line(m,b):
return np.arange(0, 20, 1)*m + b
guess = np.ones(2)
errfunc= lambda p,y: (y-line(p[0],p[1]))
parameter, sucess = optimize.leastsq(errfunc, guess, args=(data[1]))
print(parameter)
plt.plot(data[0],data[1],'o')
plt.plot(data[0],line(parameter[0],parameter[1]))
plt.show()

Plotting 2D integral function in python

Here is my first steps within the NumPy world.
As a matter of fact the target is plotting below 2-D function as a 3-D mesh:
N = \frac{n}{2\sigma\sqrt{\pi}}\exp^{-\frac{n^{2}x^{2}}{4\sigma^{2}}}
That could been done as a piece a cake in Matlab with below snippet:
[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);
But the bloody result is ugly enough to drive me trying Python capabilities to generate scientific plots.
I searched something and found that the primary steps to hit above mark in Pyhton might be acquired by below snippet:
from matplotlib.patches import Polygon
import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
sigma = 1
def integrand(x,n):
return (n/(2*sigma*np.sqrt(np.pi)))*np.exp(-(n**2*x**2)/(4*sigma**2))
t = np.linespace(0, 20, 0.01)
n = np.linespace(1, 100, 1)
lower_bound = -100000000000000000000 #-inf
upper_bound = t
tt, nn = np.meshgrid(t,n)
real_integral = quad(integrand(tt,nn), lower_bound, upper_bound)
Axes3D.plot_trisurf(real_integral, tt,nn)
Edit: With due attention to more investigations on Greg's advices, above code is the most updated snippet.
Here is the generated exception:
RuntimeError: infinity comparisons don't work for you
It is seemingly referring to the quad call...
Would you please helping me to handle this integrating-plotting problem?!...
Best
Just a few hints to get you in the right direction.
numpy.meshgrid can do the same as MatLABs function:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html
When you have x and n you can do math just like in matlab:
sigma = numpy.sqrt(2)/n
(in python multiplication/division is default index by index - no dot needed)
scipy has a lot more advanced functions, see for example How to calculate cumulative normal distribution in Python for a 1D case.
For plotting you can use matplotlibs pcolormesh:
import matplotlib.pyplot as plt
plt.pcolormesh(x,n,real_integral)
Hope this helps until someone can give you a more detailed answer.

Function that computes rk method/no plotting

import math
import matplotlib
import numpy as np
from numpy import linspace
tmax=10.0
n=2000
G=4
D=-1
m=2
t=np.linspace (0,400,n+1)
phi=10
dphi=delta=phi_dot=np.linspace(0,400,n+1)
def f(delta_dot,t):
return ((G)*(D*delta+m))
def iterate (func,phi,delta,tmax,n):
dt=tmax/(n-1)
t=0.0
for i in range(n):
phi,delta = func (phi,delta,t,dt)
t += dt
return phi
def rk_iter(phi,delta,t,dt):
k1=f(t,phi)
k2=f(t+dt*0.5,phi+k1*0.5*dt)
k3=f(t+dt*0.5,phi*k2*0.5*dt)
k4=f(t*dt,phi*k3*dt)
delta +=dt*(k1+2*k2+2*k3+k4)/6
k1=k2=k3=k4=delta=phi_dot
phi += dt*(k1+2*k2+2*k3+k4)/6
return phi,delta
runge_kutta = lambda delta, phi,tmax,n:iterate(rk_iter,delta,phi,tmax,n)
def plot_result (delta,phi,tmax,n):
dt=tmax/(n-1)
error_rk=[]
r_rk=[]
t=0.0
phi=phi_rk=phi
delta=delta_rk=delta
for i in range(n):
phi_rk,delta_rk=rk_iter(phi_rk,delta_rk,t,dt=tmax/(n-1))
t+=dt
_plot("error.png","Error","time t", "error e",error_rk)
def _plot(title,xlabel,ylabel,rk):
import matplotlib.pyplot as plt
plt.title(title)
plt.ylabel(ylabel)
plt.xlabel(xlabel)
plt.plot(rk,"r--",label="Runge-Kutta")
plt.legend(loc=4)
plt.grid(True)
plt.plot(runge_kutta,t)
print "runge_kutta=", runge_kutta(phi,delta,tmax,n)
print "tmax=",t
I have no idea how to get the function plt.show() to work. What do I have to do to open a plot window?
You haven't defined f; instead, f is being imported from matplotlib by the statement from matplotlib import *:
In [10]: import matplotlib
In [11]: matplotlib.f
Out[11]: Forward: "a"
In [12]: matplotlib.f(1,1)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-12-5843007d7dbe> in <module>()
----> 1 matplotlib.f(1,1)
TypeError: __call__() takes at most 2 arguments (3 given)
You will save yourself many headaches like this in the future if you never use the * form of the import statement in your scripts. For example, instead of from math import *, use one of these two forms:
import math
# Now refer to math.sin, math.pi, etc.
or, explicilty import only the names that you will use:
from math import sin, pi
At no point do you call the plot_result procedure. And even if you called it, you do not fill the rk and error_rk lists. You could simply use the result from the runge_kutta call,...
As commented in the other, duplicate post, you define the system equation as f(y,t) but use it as f(t,y).
There is some confusion in the usage of delta, sometimes it is the integration variable, sometimes the rk4-step update.
In the rk4-step, there are some misplaced multiplications where there should be additions. And the line
k1=k2=k3=k4=delta=phi_dot
is complete nonsense and invalidates the previous computations and makes the rk4-update in the next step meaningless.
Remove the imports of math and linspace, neither is used in the code. Move the aliasing of plt to the top and merge it with the unnecessary import of matplotlib.

Categories