Universal function with multiple array arguments - python

I am trying to make a universal function with multiple numpy array arguments using python.
import numpy as np
import matplotlib.pyplot as plt
import scipy.constants
pi = np.pi
i = 0.+1.j
c = scipy.constants.c
lam = 0.860e-6
f_c = c/lam
def refl_general(array_r, array_L, f):
array_phi = 2*pi*array_L*f/c
phi_sum = np.sum(array_phi)
exp_sum = np.exp(i*phi_sum)
r_all = np.prod(array_r)
r_in = array_r[0]
r_except_in = np.prod(array_r[1:])
return (-r_in + r_except_in*exp_sum)/(1-r_all*exp_sum)
This function works like refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([1, 1, 1]), f_c).
I'd like to plot refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([L/3, L/3, L/3]), f_c) against L = np.linspace(lam, 3*lam, 1000) without remaking the function.
I'd like to apply this function to each elements of L and get an array of each output. In other words, I want to write the following without using for.
array_L = np.linspace(lam, 3*lam, 1000)
array_signal = np.array([])
for L in array_L:
signal = np.abs(refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([L/3, L/3, L/3]), f_c))
array_signal = np.append(array_signal, signal)
plt.plot(array_L, array_signal)
Simply writing refl_general(np.array([np.sqrt(0.5), np.sqrt(0.5), np.sqrt(0.5)]), np.array([L/3, L/3, L/3]), f_c) doesn doesn't achieve the desired output since np.array([L/3, L/3, L/3]) becomes a two-dimensional array
For example, I already know how to create a universal function using np.frompyfunc.
But, this also doesn't work as expected because the argument np.array([L/3, L/3, L/3]) is a two-dimensional array.

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):

operation on Matrices with the elements in function form

I have a set of functions which are tended to be the elements of a matrix, and I have to do some + and * and / operation on them and also between each matrix element.
I am using Numpy, Sympy to do this and here is the code written on Python 2.7.
import numpy as np
import math
import cmath
import matplotlib.pyplot as pl
from cmath import*
from sympy import*
# delta, deltz and some other numbers are simple float number I changed varibles in for loop to the first value to test this section of my whole cod
f1 = Matrix([[1, 0],[ 0, 1]]) #an empty matrix from sympy
delta = 2.0*np.pi*1.6*((1.0/1530)-(1.0/(2.0*1550))) #this is a simple float number
deltz = (5*(10.0**6))/50
def apdFunc(x):
return np.exp(-2*np.log(2)*((x-(5/2))/5)**2)
def modFunc(x):
return (1+np.cos((2*np.pi/1)*x))
d1 = np.linspace(-20.0, 20.0, 5000)
apdFunc = apdFunc(d1)
modFunc = modFunc(d2)
Profile = modFunc*apdFunc
sig = (np.pi/1530)*fbgProfile + delta
kaa = (np.pi/1530)*fbgProfile
j = sqrt(-1)
gammab = np.sqrt(kaa**2.0-sig**2.0)
#Matrix elements definition
f11 = np.cosh(gammab*deltz)-1j*(sig/gammab)*np.sinh(gammab*deltz)
f22 = np.cosh(gammab*deltz)+1j*(sig/gammab)*np.sinh(gammab*deltz)
f12 = -1j*(kaa/gammab)*np.sinh(gammab*deltz)
f21 = 1j*(kaa/gammab)*np.sinh(gammab*deltz)
f1 = f1*Matrix([[f11, f12],[ f21, f22]])
PO=f1[0,0]
NO=f1[1,0]
REF=abs((NO/PO)**2)
pl.plot(d3,REF)
pl.show()
print f1[0,0]
print PO
print REF
The first problem is : gammab=np.sqrt(kaa**2.0-sig**2.0) that numpy can't accept complex number I mean negative value under sqrt and if I don't use Numpy I can't do Operation on them because kaa and sig are functions.
Second : I cant print the matrix elements (after reversing kaa**2.0-sig**2.0 and solving first problem), thus I can't plot the REF=abs((NO/PO)**2) and an error apears telling
AttributeError: 'ImmutableDenseNDimArray' object has no attribute 'as_coeff_Mul'
Any help appreciated and if you can introduce a reference to learn how to solve the problem.

Multiple return using scipy.odeint method in Python

I am trying to use scipy.odeint() method in order to solve an second order partial derivative function.
I can do that for a single value of constant k, which is a constant of the function I have.
But I want to try this solution for many values of k.
To do so, I included the values that I want in a list k, and going through a loop I want to plug in these values for the final solution as arguments.
However, I am getting an error
error: Extra arguments must be in a tuple
import numpy as np
from scipy.integrate import odeint
### Code with a single value of K.THAT WORKS FINE!!!! ###
k = 1 #attributes to be changed
t = [0.1,0.2,0.3] #Data
init = [45,0] #initial values
#Function to apply an integration
def f(init, t, args=(k,)):
dOdt = init[1]
dwdt = -np.cos(init[0]) + k*dOdt
return [dOdt, dwdt]
#integrating function that returns a list of 2D numpy arrays
zCH = odeint(f,init,t)
################################################################
### Code that DOES NOT WORK!###
k = [1,2,3] #attributes to be changed
t = [0.1,0.2,0.3] #Data
init = [45,0] #initial values
#Function to apply an integration
def f(init, t, args=(k,)):
dOdt = init[1]
dwdt = -np.cos(init[0]) + k*dOdt
return [dOdt, dwdt]
solutions = []
for i in k:
#integrating function that returns a list of 2D numpy arrays
zCH = odeint(f,init,t,(k[i-1]))
solutions.append(zCH)```
It has to do with the way you are passing k into your function f().
The following changes the value of k on each iteration
k_list = [1,2,3] #attributes to be changed
t = [0.1,0.2,0.3] #Data
init = [45,0] #initial values
#Function to apply an integration
def f(init, t, args=(k,)):
dOdt = init[1]
dwdt = -np.cos(init[0]) + k*dOdt
return [dOdt, dwdt]
solutions = []
for k in k_list:
#integrating function that returns a list of 2D numpy arrays
zCH = odeint(f, init, t)
solutions.append(zCH)

Replicating matlab filter in python

I am re-writing a matlab filter script into python and have vastly different outputs. Does anyone know how to make these functions similar?
There was some preliminary calculations made to find the equivalent ripple and other factors.
Python Script:
from scipy import signal
import math as m
import matplotlib.pyplot as plt
# Variable Values:
total_ripple = -20*m.log10(0.001) #get decibels
fsamp = 100
Nyqu = fsamp/2
trans_width = (0.7 - 0.1)/Nyqu
cut = (0.7+0.1)/2*(Nyqu)
# Script:
numtaps, beta = signal.kaiserord(total_ripple, trans_width)
taps = signal.firwin(numtaps, cutoff=cut, width = trans_width, fs = fsamp, window=('kaiser',numtaps+1, beta), scale=False, pass_zero=True)
filtered_data = (signal.lfilter(taps, 1, data1, axis = 0)).tolist()
Matlab Script:
mags = [1, 0]
devs = [0.001, 0.1]
fcuts = [0.1 0.7]
fsamp = 100
[n,Wn,beta,ftype] = kaiserord(fcuts,mags,devs,fsamp);
hh = fir1(n,Wn,ftype,kaiser(n+1,beta),'noscale');
filteredData = filter(hh,1,data);
(Edit: added variable values)
I know that the fcuts will vary between matlab and python. Python only accepts a single fcuts value in decibels for stopband. Simply plotting taps & hh gives different plots. The final plots with the actual data is different as well.

Numpy roots function and pyplot plot

I want to plot the two solutions of quadratic equation as a function of a parameter ( function coeff(t) ). I am using function numpy.roots (I am sure that all roots are real in this case), and I am trying to invoke it from within pyplot.plot as below:
import numpy as np
import matplotlib.pyplot as plt
r = 3.74
def coeff(pp):
return np.array([pp-1,r+1-0.5*pp,-r])
def sroot(t):
return np.roots(coeff(t))
a = np.linspace(0,0.9,100)
fig = plt.figure()
plt.plot(a,sroot(a)[0,:])
plt.plot(a,sroot(a)[1,:])
plt.show()
I get error message:
File "quest.py", line 18, in <module>
plt.plot(a,sroot(a)[0,:])
File "quest.py", line 10, in sroot
return np.roots(coeff(t))
File "/usr/lib64/python2.7/site-packages/numpy/lib/polynomial.py", line 218, in roots
p = p.astype(float)
I understand that the numpy.roots takes only list of parameters and is unable to recognize a row in array 3xlen(a). Is there a way to do it in one line, preferably inside the pyplot.plot? I would like to avoid using loop.
This is because you transform all of your coefficient at once and try to call the numpy roots solver on all of them. np.roots only accept 1-d array and solves a single polynomial. Here is a script that does what you want:
import numpy as np
import matplotlib.pyplot as plt
# Parameters
r = 3.74
T = np.linspace(0.0,0.9,100)
# Coefficients
C = np.zeros((len(T),3))
C[:,0] = T-1
C[:,1] = r + 1 - 0.5*T
C[:,2] = r
# Roots
R = np.zeros((len(T),2))
for i in range(len(T)):
R[i] = np.roots(C[i])
# Plot
fig = plt.figure()
plt.plot(T,R[:,0])
plt.plot(T,R[:,1])
plt.show()

Categories

Resources