Function that computes rk method/no plotting - python

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.

Related

Define and plot constant function in 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))

TypeError: deriv() takes 2 positional arguments but 4 were given

I'm getting the above error. I understand in principle what it means, but can't really see how it applies to my code
#project starts here
import numpy as np
import scipy.integrate
import matplotlib.pyplot as plt
from numpy import pi
from scipy.integrate import odeint
def deriv(cond,t):
for q in range (0,N):
i=6*q
dydt[i]=cond[i+3]
dydt[i+1]=cond[i+4]
dydt[i+2]=cond[i+5]
r=sqrt((cond[i])**2 +(cond[i+1])**2 +(cond[i+2])**2)
dydt[i+3]=-G*M*cond[i]/(r**3)
dydt[i+4]=-G*M*cond[i+1]/(r**3)
dydt[i+5]=-G*M*cond[i+2]/(r**3)
return dydt
G=1
M=1
N=12
vmag=((G*M)/(2))**(0.5)
theta = np.linspace(0,2*pi,N)
x=2*np.cos(theta)
y=2*np.sin(theta)
vx=-vmag*np.sin(theta)
vy=vmag*np.cos(theta)
z=np.zeros(N)
vz=np.zeros(N)
t=np.linspace(0,30,100)
cond=list(item for group in zip(x,y,z,vx,vy,vz) for item in group)
sln=odeint(deriv, cond, t, args=(G,M))
Any ideas where it is coming from? I feel like I have given the correct number of arguments.
You are sending 4 arguments to deriv. Per the odeint docs, you have a function deriv whose first two arguments must be y and t. When you call odeint(deriv,cond,t,...) the cond and t are automatically sent as the first two arguments to deriv. All you need to do is to make deriv(cond,t,G,M).
If you look documantation for odeint [1], you will see that your fucntion to call in oneint must be in form func(y, t0, ...). So when you call odeint(deriv, cond, t, args=(G,M)) it actually call your function as deriv(cond,t,G,m). But your function takes just 2 argument.
[1] http://docs.scipy.org/doc/scipy-0.17.0/reference/generated/scipy.integrate.odeint.html

Only length-1 arrays can be converted to Python scalars with log

from numpy import *
from pylab import *
from scipy import *
from scipy.signal import *
from scipy.stats import *
testimg = imread('path')
hist = hist(testimg.flatten(), 256, range=[0.0,1.0])[0]
hist = hist + 0.000001
prob = hist/sum(hist)
entropia = -1.0*sum(prob*log(prob))#here is error
print 'Entropia: ', entropia
I have this code and I do not know what could be the problem, thanks for any help
This is an example of why you should never use from module import *. You lose sight of where functions come from. When you use multiple from module import * calls, one module's namespace may clobber another module's namespace. Indeed, based on the error message, that appears to be what is happening here.
Notice that when log refers to numpy.log, then -1.0*sum(prob*np.log(prob)) can be computed without error:
In [43]: -1.0*sum(prob*np.log(prob))
Out[43]: 4.4058820963782122
but when log refers to math.log, then a TypeError is raised:
In [44]: -1.0*sum(prob*math.log(prob))
TypeError: only length-1 arrays can be converted to Python scalars
The fix is to use explicit module imports and explicit references to functions from the module's namespace:
import numpy as np
import matplotlib.pyplot as plt
testimg = np.random.random((10,10))
hist = plt.hist(testimg.flatten(), 256, range=[0.0,1.0])[0]
hist = hist + 0.000001
prob = hist/sum(hist)
# entropia = -1.0*sum(prob*np.log(prob))
entropia = -1.0*(prob*np.log(prob)).sum()
print 'Entropia: ', entropia
# prints something like: Entropia: 4.33996609845
The code you posted does not produce the error, but somewhere in your actual code log must be getting bound to math.log instead of numpy.log. Using import module and referencing functions with module.function will help you avoid this kind of error in the future.

Plotting a signal in Python

I'm trying to plot a simple signal in python, and when i run this it doesn't show any error only 'Restart' and a blank space
from pymatlab import*
import numpy as np
from numpy import sqrt
import matplotlib.pyplot as plt
import scipy as sp
import math
(hashtags) n, coef, freq, phase
def sinyal(N,c,f,p):
y=np.zeros(N)
t=np.linspace(0,2*pi,N)
Nf=len(c)
for i in range(Nf):
y+=c[i]*np.sin(f[i]*t)
return y;
# Signal Generator
c=[2,5,10]
f=[50, 150, 300]
p=[0,0]
N=2000
x=np.linspace(0,2.0*math.pi,N)
y=sinyal(N,c,f,p)
plt.plot(x[:100],y[:100])
plt.show()
The code you posted has a logical indentation error. The call to sinyal is indented one level, placing it inside the definition of sinyal itself. So although sinyal gets defined, it never gets called.
Using 4 spaces for indentation may help you avoid this error in the future.
Your code basically works (apart from some formatting errors and other oddities). I don't have pymatlab but it isn't necessary for this.
import numpy as np
from numpy import sqrt
import matplotlib.pyplot as plt
import scipy as sp
import math
def sinyal(N,c,f,p):
y=np.zeros(N)
t=np.linspace(0,2*np.pi,N)
Nf=len(c)
for i in range(Nf):
y+=c[i]*np.sin(f[i]*t)
return y;
# Signal Generator
c=[2,5,10]
f=[50, 150, 300]
p=[0,0]
N=2000
x=np.linspace(0,2.0*math.pi,N)
y=sinyal(N,c,f,p)
plt.plot(x[:100],y[:100])
plt.show()

Matplotlib plotting with float values for x

I have tried to find the answer to this question, maybe its very easy and thats why i cant.
If I have made a Gaussian function and I want to plot it with Matplotlib.pyplot.plot, how can i do that with float values. I.e. values from -20<=x<=20 in increments of 0.1
import matplotlib.pyplot as plt
import math
from math import exp
import numpy
#Parameters for the Gaussian
A=1
c=10
t=0
a=1
x=[]
p=-20.
while p<=20:
x.append(p)
p+=0.1
def Gaussian(A,c,t,a,x):
return A*exp(-((c*t-x)^2 /(4*a*c^2)))
plt.plot(x,Gaussian(A,c,t,a,x))
plt.show()
The Error i get is:
Traceback (most recent call last):
File "C:--------/Gaussian Function.py", line 21, in <module>
plt.plot(x,Gaussian(A,c,t,a,x))
File "C:--------/Gaussian Function.py", line 19, in Gaussian
return A*exp(-((c*t-x)^2 /(4*a*c^2)))
TypeError: unsupported operand type(s) for -: 'int' and 'list'
The problem has nothing to do with matplotlib. You will get the same error if you just call Gaussian(A, c, t, a, x) without using matplotlib at all. Your function accepts an argument x that is a list, and then tries to do stuff like c*t-x. You can't subtract a list from a number. As the error message suggests, you should probably make x a numpy array, which will allow you to do these kinds of vectorized operations on it.
There are some mistakes in your code. The corrected one is below:
import matplotlib.pyplot as plt
import numpy as np
#Parameters for the Gaussian
A, c, t, a = 1, 10, 0, 1
x = np.arange(-20,20,0.1) #use this instead
def Gaussian(A,c,t,a,x):
return A*np.exp(-((c*t-x)**2/(4*a*c**2))) #power in Python is ** not ^
plt.plot(x,Gaussian(A,c,t,a,x))
plt.show()
and result is:

Categories