Can't draw function using python - python

I have made a function RC(n) that given any n changes the digits of n according to a rule. The function is the following
def cfr(n):
return len(str(n))-1
def n_cfr(k,n):
J=str(k)
if "." in J:
J2=J.replace(".", "")
return J2[n-1]
else:
return J[n]
def RC(n):
if "." not in str(n):
return n+1
sum=0
val=0
for a in range(1,cfr(n)+1):
O=(int(n_cfr(n,a)))*10**(-a+1)
if int(n_cfr(n,a))==9:
val=0
else:
val=O+10**(-a+1)
sum=sum+val
return sum
I would like to draw this function for non-integers values of n. A friend gave me this code that he used in other functions but it doesn't seem to work for me:
def draw(f,a,b,res):
import numpy as np
import matplotlib.pyplot as plt
x=[a+(b-a)*i/res for i in range(0,res)]
y=[f(elm) for elm in x]
plt.plot(np.asarray(x), np.asarray(y))
plt.show()
I'm not familiar with plotting functions using python so could anyone give me some help?
Thanks in advance

The line in your function should be x = list(range(a, b, res)) the first two arguments of range are start and stop. Here is a better version of draw:
def draw(f, a, b, res):
import numpy as np
import matplotlib.pyplot as plt
x = list(range(a, b, res))
plt.plot(x, map(f, x))
plt.show()

Related

plot multiple curves on same plot inside function

I have a following function with takes 2 arguments psi,lam and returns 1 array y.
lam=np.arange(0,1,0.1)
psi=np.deg2rad(np.arange(0,361,1))
def test(psi,lam):
y=[]
for i in range(len(lam)):
sin_psi = np.sin(psi)
cos_psi = np.cos(psi)
sin_beta = lam*sin_psi
cos_beta = np.sqrt(1.0 - sin_beta**2)
ssin_pb = sin_psi*sin_beta
y.append((lam*(cos_psi/cos_beta)**2 - ssin_pb)/cos_beta + cos_psi)
plt.plot(psi,y[i])
return y
I would like the function to return range(len(lam))=10 plots of y on the vertical axis against psi on x axis.
However, it seems to be only plotting the same curve multiple times. Not sure what I am missing?
import matplotlib.pyplot as plt
import numpy as np
lam=np.arange(0,1,0.1)
psi=np.deg2rad(np.arange(0,361,1))
def test(angle,var):
sin_psi = np.sin(psi)
cos_psi = np.cos(psi)
sin_beta = var*sin_psi
cos_beta = np.sqrt(1.0 - sin_beta**2)
ssin_pb = sin_psi*sin_beta
return ((var*(cos_psi/cos_beta)**2 - ssin_pb)/cos_beta + cos_psi)
for i in lam:
plt.plot(psi,test(psi,i))
plt.show()
I moved the variable outside of the function, this way you may also use it for other cases. The only other thing is that you should call plt.show() after you're done drawing.
Your code has several problems the main being that the return function was inside the loop interrupting it after the first iteration. Imitating your code structure as closely as possible, we can rewrite the code as:
import numpy as np
import matplotlib.pyplot as plt
def test(psi,lam):
y=[]
for curr_lam in lam:
sin_psi = np.sin(psi)
cos_psi = np.cos(psi)
sin_beta = curr_lam*sin_psi
cos_beta = np.sqrt(1.0 - sin_beta**2)
ssin_pb = sin_psi*sin_beta
val = (curr_lam * (cos_psi/cos_beta)**2 - ssin_pb)/cos_beta + cos_psi
y.append(val)
plt.plot(psi, val)
plt.show()
return y
lam=np.arange(0, 1, 0.1)
psi=np.deg2rad(np.arange(0,361,1))
y = test(psi, lam)
print(y)
Sample output:
As Johan mentioned in the comments, you should also directly iterate over list/arrays. If you need to combine arrays, use
for x1, x2 in zip(arr1, arr2):
If you absolutely need the index value, use
for i, x in enumerate(arr):

How to transform a np.array into a function?

I have the following np.array which describes a rectangular wave. I would like to transform it into a callable function with a continuous argument. The np.array is:
import matplotlib.pyplot as plt
import numpy as np
from numpy.random import seed
from numpy.random import rand
def piecewise_control( off_times,amp_inj, period_inj ):
def select(T):
return lambda t: (-T/2 <= t) & (t < T/2)
def pulse_train(t, at, shape):
return np.sum(shape(t - at[:,np.newaxis]), axis=0)
for i in range(1,len(off_times)):
off_times[i] += off_times[i-1] + period_inj
return amp_inj*pulse_train(t,off_times,shape=select(period_inj))
t=np.linspace(0,100,10000)
off_times = 10*rand(10)
period_inj = 1
amp_inj = 1
control = piecewise_control( off_times,amp_inj, period_inj )
plt.plot(t,control)
plt.show()
This answer inspired me.
The plot is the following:
The question is: can we transform the array control into a function with a continuous argument?
Of course if we did:
def ccontrol(t, control):
return control[t]
unfortunately we would get a function which only depends on integers.
You can subclass numpy.ndarray and implement the __call__ method:
import numpy as np
class MyArray(np.ndarray):
def __call__(self, idx):
return self[idx]
control = np.random.rand(100)
control_view = control.view(MyArray)
print(control_view(5), control[5])
For interpolation you can use scipy.interpolate. In fact, interpolation routines can return functions that you can call with any input, not necessarily integers.

EDIT:plotting the function, x and y must have the same first dimension

UPDATE:
Using the answer from before, I was able to call the function. Now, I tried to increase the difficulty a step-further.
I understand that using this works:
def sinesum(t, b):
return sum(b*sin(n*t))
for i in range(0, 10, 1):
b = i
n = i
t = i
print(sinesum(i,i))
Although, I want to be able to plot it with:
import matplotlib.pyplot as plt
t = np.linspace(-10, 10, 20)
plt.plot(t, sinesum(i,i))
plt.show
I get nothing, how do I plot with the function output as y?
when I remove (i, i) and include (t, b) I get
x and y must have the same first dimension, but have shapes (20,) and (1,)
I understand that this is because the function only calls a single value, how do I get it so that sinesum(i,i) will return the right amount of dimensions for the plot?
You should calculate every value before plotting it:
res = []
for v in t:
res.append(sinesum(v,b))
plt.plot(t,res)
or using list comprehension:
plt.plot(t, [sinesum(v,b) for v in t])
Did you meen?
def f(x):
return 4*x + 1
for i in range(100):
print(f(i))

Spherical Bessel Functions causing "invalid __array_struct__"

I'm trying to calculate the differential cross section(function of and angle and the "order" l) in a scattering problem.
I would like to do this for different values of l and plot the cross section.
I think that the division of the Bessel functions is the problem but I don't know how to solve it.
Any solutions/tips?
Thanks
This is my code:
import numpy as np
import scipy as sp
from scipy import special
def j_l(l,k):
sp.special.spherical_jn(l, k)
return np.ndarray
def j_l1(l,k):
sp.special.spherical_jn(l, k, True)
return np.ndarray
def n_l(l, k):
sp.special.spherical_yn(l, k)
return np.ndarray
def n_l1(l, k):
sp.special.spherical_yn(l, k, True)
return np.ndarray
def delta_l(k_1, k_2,r, l):
np.arctan(np.divide(k_1*np.divide(j_l1(l,k_1),j_l(l,k_1))*j_l(l,k_2)-k_2*r*j_l1(l,k_2)),(k_1*np.divide(j_l1(l,k_1),j_l(l,k_1))*n_l(l,k_2)-k_2*r*n_l1(l,k_2)))
def dcross(l,t,k_2,k_1):
(1/k_2*(2*l+1)*np.exp(delta_l(k_1,k_2,2,l))*np.sin(delta_l(k_1,k_2,2,l))*sp.special.lpmv(0, l, np.cos(t)))**2
t=np.linspace(0, 10, 10000)
fig = plt.figure()
plt.plot(t,dcross(1,t,1,0.5))
fig.savefig('dcross.png')
plt.show() ```
My physics is a little rusty so I could not check the formulas but there were two problems: a paranthesis-error in the delta_l (the outer true divide) and the proper returns on the Bessel functions and its derivatives:
import matplotlib.pyplot as plt
import numpy as np
import scipy as sp
from scipy import special
def j_l(l,k):
return sp.special.spherical_jn(l, k)
#return np.ndarray
def j_l1(l,k):
return sp.special.spherical_jn(l, k, True)
#return np.ndarray
def n_l(l, k):
return sp.special.spherical_yn(l, k)
#return np.ndarray
def n_l1(l, k):
return sp.special.spherical_yn(l, k, True)
#return np.ndarray
def delta_l(k_1, k_2,r, l):
return np.arctan(np.divide(k_1*np.divide(j_l1(l, k_1), j_l(l ,k_1))*j_l(l, k_2)-k_2*r*j_l1(l, k_2),
(k_1*np.divide(j_l1(l,k_1), j_l(l,k_1))*n_l(l, k_2)-k_2*r*n_l1(l, k_2))))
def dcross(l,t,k_2,k_1):
return (1/k_2*(2*l+1)*np.exp(delta_l(k_1,k_2,2,l))*np.sin(delta_l(k_1,k_2,2,l))*sp.special.lpmv(0, l, np.cos(t)))**2
t=np.linspace(0, 10, 10000)
fig = plt.figure()
plt.plot(t,dcross(1,t,1,0.5))
#fig.savefig('dcross.png')
plt.show()
producing (if this is what you are looking for):

Jacobi Method & Basic Matrix Math using NUMPY

I'm getting an import error for "norm". What am I not doing correct??
I'm open to constructive feedback on improving the code, however I have to keep the parameters as they are!
Thanks!!!
Code is below:
import numpy as np
from numpy import norm, inalg, array, zeros, diag, diagflat, dot, linalg
"""Test Case Data"""
A = np.matrix([[4,-1,-1],[-2,6,1],[-1,1,7]])
b = np.matrix([[3],[9],[-6]])
x = np.matrix([[0],[0],[0]])
"""Main Function"""
def jacobi(A, b, x, Tolerance, Iterations):
V = np.diag(A)
D = np.diag(V)
R = D-A
D_I = D.I
D = np.asmatrix(D)
Counter_1 = 1
tol_gauge = 100
while Counter_1 <= Iterations:
# I considered using the "dot" function in NUMPY but I was wary of mixed results
iterative_approach_form = D_I * ((R*x)+b)
tol_gauge = np.linalg.norm(iterative_approach_form-x)
x = iterative_approach_form
if initial_tol <= Tolerance:
return("The Solution x = {},y={}, z={} ".format(x[0], x[1], x[2]))
return("The Solution was found in %s interation(s)" %(Counter_1))
else:
pass
Counter_1 +=1
return("The Solution was not found in {} iteration(s)".format(Iterations))
You need to specify which numpy module you are importing from. The following works if you want to use a function only by its name:
from numpy import linalg
from numpy.linalg import norm
from numpy import zeros, array, diag, diagflat, dot
Looking at you code however, you don't need the second import line, because in the rest of the code the numpy functions are specified according to the accepted norm. For example, norm is already present in your code as np.linalg.norm.
There are three more issues with your code: 1) initial_tol is not assigned a value; 2) tol_gauge is assigned but not used in the code; 3) the last return statement is not indented properly (perhaps only here) and the same is very likely for the block in your while loop.

Categories

Resources