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.
Related
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):
How to do zero-skewness log transform in Python?
For example in Stata it is implemented in lnskew0 (see https://www.stata.com/manuals13/rlnskew0.pdf).
I didn't find an implementation in Python. Is anyone aware of an implementation?
Otherwise, a first try would be:
from scipy.stats import skew
import numpy as np
from scipy.optimize import root_scalar
def lnskew0(x):
def skew_ln(k):
return skew(np.log(x - k))
res = root_scalar(
skew_ln,
bracket=[-x.min(), x.max()*0.99999],
method='bisect'
)
return np.log(x - res.root)
Works fine on numpy arrays with only positive numbers. How is Stata's lnskew0 implemented that it works with negative numbers as well?
I gave it another try so that it works with negative numbers as well:
from scipy.stats import skew
import numpy as np
from scipy.optimize import root_scalar
def lnskew0(x):
x0 = x + 1
def skew_ln_pos(k):
with np.errstate(all='ignore'):
return skew(np.log(x0 - k))
res_pos = root_scalar(
skew_ln_pos,
bracket=[-150, 150],
method='bisect'
)
def skew_ln_neg(k):
with np.errstate(all='ignore'):
return skew(np.log(-x0 - k))
res_neg = root_scalar(
skew_ln_neg,
bracket=[-150, 150],
method='bisect'
)
res = (res_pos.root - 1, res_neg.root + 1)
lnskew0_res = (
np.log(x - res[0]),
np.log(-x - res[1])
)
whichmin = np.nanargmin([abs(skew(x)) for x in lnskew0_res])
return lnskew0_res[whichmin]
Note: It still has one issue. The bracket of the root_scalar needs to be choosen manually.
I have a 2D numpy-array as input for a basic sigmoid-classifier.
I would like the classifier to return an array with the probabilities.
import numpy as np
def sigmoid(x):
sigm = 1 / (1 + np.exp(-x))
return sigm
def p(D, w, b):
prob=sigmoid(np.dot(D[:][7],w)+b)
return prob
How can I change p() so that it returns a 1D numpy array with the probabilities listed in order of the input data ?
Atm "prob" is an array of length 14, however the input array "D" is over 400 in size, so there is an error somewhere in the logic.
EDIT: The issue is the incorrect slicing of the array. One has to use D[:,7] instead of D[:][7] to extract a column.
Perhaps like this:
import numpy as np
def sigmoid(x):
sigm = 1 / (1 + np.exp(-x))
return sigm
def p(D, w, b):
prob=sigmoid(np.dot(D[:][7],w)+b)
return np.ravel(prob)
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.
I would like to plot a 1D profile of a 2D image along an arbitrary line. The code below loads the image data hosted on github and plots it:
import urllib
import numpy as np
import matplotlib.pyplot as plt
url = "https://gist.github.com/andreiberceanu/7141843/raw/0b9d50d3d417b1cbe651560470c098700df5a1fc/image.dat"
f = urllib.urlopen(url)
data = np.loadtxt(f)
plt.imshow(data)
The red line in the plot above was drawn by hand, as an example. I suppose one can parametrize it in the form a*x + b. I am also guessing some sort of interpolation is necessary, because the line passes though points which may not be part of the original 2D array of data.
You want to use scipy.ndimage.map_coordinates. You need to build up a 2xn array that is the coordinates at which to sample and then do map_coordinates(im, samples).
I think this is it:
def sliceImage(I, a, b, *arg, **kws):
from scipy import linspace, asarray
from scipy.ndimage import map_coordinates
from scipy.linalg import norm
dst = norm(asarray(b) - a) + 1
return map_coordinates(I, [linspace(strt, end, dst)
for strt, end in zip(a, b)],
*arg, **kws)
Edit:
On further consideration, I think this is more elegant:
def sliceImage(I, a, b, *arg, **kws):
from scipy import linspace, asarray
from scipy.ndimage import map_coordinates
from scipy.linalg import norm
a = asarray(a)
b = asarray(b)
dst = norm(b - a) + 1
return map_coordinates(I, (a[:,newaxis] * linspace(1, 0, dst) +
b[:,newaxis] * linspace(0, 1, dst)),
*arg, **kws)
Edit: Thanks tcaswell: Added 1 to dst.