IDL WHERE in python? - python

I am having trouble translating an old IDL script to python- my issue lies in understanding exactly how to interpret IDL's "WHERE" function.
Here is my code:
FUNCTION noise,day,y
N = N_ELEMENTS(y)
valid = WHERE(ABS(day[0:N-3]-day[2:N-1]) LT 20,cc)
IF cc LT 2 THEN RETURN,[-9.99,-9.99,-9.99,-9.99]
y_int = (y[0:N-3] * (day[2:N-1] - day[1:N-2]) + y[2:N-1] * (day[1:N-2] - day[0:N-3]))/ (day[2:N-1] - day[0:N-3])
dif = ABS(y_int - y[1:N-2])
difR = ABS(y_int/y[1:N-2] - 1.)
dif = dif [valid]
difR= difR[valid]
; Remove 5% of higher values
Nv = LONG(cc*0.95)
s = SORT(dif) & s = s[0:Nv-1]
noise5 = SQRT(TOTAL(dif[s]^2)/(Nv-1)) ; Absolu Noise minus 5% of higher values
noise = SQRT(TOTAL(dif^2)/(cc-1)) ; Absolu Noise
s = SORT(difR) & s = s[0:Nv-1]
noiseR5 = SQRT(TOTAL(difR[s]^2)/(Nv-1)) ; Relative Noise minus 5% of higher values
noiseR = SQRT(TOTAL(difR^2)/(cc-1)) ; Relative Noise
RETURN,[noise5,noiseR5*100.,noise,noiseR*100.]
END
Can anyone help me understand the python equivalent? TY.

I would translate:
valid = WHERE(ABS(day[0:N-3]-day[2:N-1]) LT 20,cc)
as:
valid = (numpy.abs(day[0:-2] - day[2:]) < 20).nonzero()

Related

Generate Reference Point in nsga3

I am working on evolutionary algorithm and need a way to generate reference point (Das and Dennis approach) in python. I have no idea and struck in this part can somebody please help to write this code.Thanks in advance I have matlab code but not understanding it how to convert to python.
function Zr = GenerateReferencePoints(M, p)
Zr = GetFixedRowSumIntegerMatrix(M, p)' / 4; #Not understanding the use of {'}
end
function A = GetFixedRowSumIntegerMatrix(M, RowSum)
if M < 1
error('M cannot be less than 1.');
end
if floor(M) ~= M
error('M must be an integer.');
end
if M == 1
A = RowSum;
return;
end
A = [];
for i = 0:RowSum
B = GetFixedRowSumIntegerMatrix(M - 1, RowSum - i);
A = [A; i*ones(size(B,1),1) B]; #What is this function doing not getting it
end
end
I don't understand RowSum used for which purpose it is used

Array too big for division in matlab but not python

The problem I have is array too big in Matlab. The array data comes from audio file. I want to get the impulse response.
I first FFT the original and recorded audio. Then the division of recorded by original. Lastly inverse FFT to get the impulse response. That was what I planned to do but I got stuck at the division part.
Stuck using Matlab, I found a python code that can do it just fine. I rewrite the code into Matlab and the problem is back again. The code is incomplete but it is enough to show the problem.
Hope to get many advice and criticism. Thanks
Planned to do but failed so moved on to the next code
[y_sweep,Fs] = audioread('sweep.wav');
[y_rec,Fs] = audioread('edit_rec_sweep_laptop_1.2.wav');
fft_y1 = abs(fft(y_rec(:,1)));
fft_y2 = abs(fft(y_rec(:,2)));
fft_x = abs(fft(y_sweep));
fft_h1 = fft_y1/fft_x;
% fft_h2 = fft_y2/fft_x;
% fft_h = [fft_h1,fft_h2];
% h1 = ifft(fft1_h);
'Translated' code from python but still failed thus came here
[a,fs] = audioread('sweep.wav'); % sweep
[b,fs] = audioread('rec.wav'); % rec
a = pad(a,fs*50,fs*10);
b = pad(b,fs*50,fs*10);
[m,n] = size(b);
h = zeros(m,n);
for chan = 1:2
b1 = b(:,1);
ffta = abs(fft(a));
fftb = abs(fft(b1));
ffth = fftb / ffta;
end
pad.m function (translated from python but should be correct)
function y = pad(data, t_full, t_pre)
[row_dim,col_dim] = size(data);
t_post = t_full - row_dim - t_pre;
if t_post > 0
if col_dim == 1
y = [zeros(t_pre,1);data;zeros(t_post,1)];
% width = [t_pre,t_post];
else
y1 = [zeros(t_pre,1);data(:,1);zeros(t_post,1)];
y2 = [zeros(t_pre,1);data(:,2);zeros(t_post,1)];
y = [y1,y2];
% width = [[t_pre,t_post],[0,0]];
end
else
if col_dim == 1
y = [zeros(t_pre,1);data(t_full - t_pre:end,1)];
% width = [t_pre,0];
else
y = [zeros(t_pre,1);data(t_full - t_pre:end,1)];
% width = [[t_pre,0],[0,0]];
end
end
end
Error
Error using \
Requested 4800000x4800000 (171661.4GB) array exceeds
maximum array size preference. Creation of arrays
greater than this limit may take a long time and
cause MATLAB to become unresponsive. See array size
limit or preference panel for more information.
Error in impulseresponse (line 13)
ffth = fftb / ffta;
The forward slash is shorthand in MATLAB for mrdivide(). This is for solving systems of linear matrix equations. What I think you want is rdivide which is denoted by ./.
c = a/b is only equivalent to standard division if b is scalar.
c = a./b is element-wise division, where every element of a is divided by the corresponding element of b.
[1 2 3] ./ [2 4 9]
>> ans = [0.5, 0.5, 0.3333]
So the last active line of your "planned to do" code becomes
fft_h1 = fft_y1 ./ fft_x;

Writing a while loop for error function erf(x)?

I understand there is a erf (Wikipedia) function in python. But in this assignment we are specifically asked to write the error function as if it was not already implemented in python while using a while loop.
erf (x) is simplified already as : (2/ (sqrt(pi)) (x - x^3/3 + x^5/10 - x^7/42...)
Terms in the series must be added until the absolute total is less than 10^-20.
First of all - SO is not the place when people code for you, here people help you to solve particular problem not the whole task
Any way:
It's not too hard to implement wikipedia algorithm:
import math
def erf(x):
n = 1
res = 0
res1 = (2 / math.sqrt(math.pi)) * x
diff = 1
s = x
while diff > math.pow(10, -20):
dividend = math.pow((-1), n) * math.pow(x, 2 * n + 1)
divider = math.factorial(n) * (2 * n + 1)
s += dividend / divider
res = ((2 / math.sqrt(math.pi)) * s)
diff = abs(res1 - res)
res1 = res
n += 1
return res
print(erf(1))
Please read the source code carefully and post all questions that you don't understand.
Also you may check python sources and see how erf is implemented

Why is the computing of the value of pi using the Machin Formula giving a wrong value?

For my school project I was trying to compute the value of using different methods. One of the formula I found was the Machin Formula that can be calculated using the Taylor expansion of arctan(x).
I wrote the following code in python:
import decimal
count = pi = a = b = c = d = val1 = val2 = decimal.Decimal(0) #Initializing the variables
decimal.getcontext().prec = 25 #Setting percision
while (decimal.Decimal(count) <= decimal.Decimal(100)):
a = pow(decimal.Decimal(-1), decimal.Decimal(count))
b = ((decimal.Decimal(2) * decimal.Decimal(count)) + decimal.Decimal(1))
c = pow(decimal.Decimal(1/5), decimal.Decimal(b))
d = (decimal.Decimal(a) / decimal.Decimal(b)) * decimal.Decimal(c)
val1 = decimal.Decimal(val1) + decimal.Decimal(d)
count = decimal.Decimal(count) + decimal.Decimal(1)
#The series has been divided into multiple small parts to reduce confusion
count = a = b = c = d = decimal.Decimal(0) #Resetting the variables
while (decimal.Decimal(count) <= decimal.Decimal(10)):
a = pow(decimal.Decimal(-1), decimal.Decimal(count))
b = ((decimal.Decimal(2) * decimal.Decimal(count)) + decimal.Decimal(1))
c = pow(decimal.Decimal(1/239), decimal.Decimal(b))
d = (decimal.Decimal(a) / decimal.Decimal(b)) * decimal.Decimal(c)
val2 = decimal.Decimal(val2) + decimal.Decimal(d)
count = decimal.Decimal(count) + decimal.Decimal(1)
#The series has been divided into multiple small parts to reduce confusion
pi = (decimal.Decimal(16) * decimal.Decimal(val1)) - (decimal.Decimal(4) * decimal.Decimal(val2))
print(pi)
The problem is that I am getting the right value of pi only till 15 decimal places, no matter the number of times the loop repeats itself.
For example:
at 11 repetitions of the first loop
pi = 3.141592653589793408632493
at 100 repetitions of the first loop
pi = 3.141592653589793410703296
I am not increasing the repetitions of the second loop as arctan(1/239) is very small and reaches an extremely small value with a few repetitions and therefore should not affect the value of pi at only 15 decimal places.
EXTRA INFORMATION:
The Machin Formula states that:
π = (16 * Summation of (((-1)^n) / 2n+1) * ((1/5)^(2n+1))) - (4 * Summation of (((-1)^n) / 2n+1) * ((1/239)^(2n+1)))
That many terms is enough to get you over 50 decimal places. The problem is that you are mixing Python floats with Decimals, so your calculations are polluted with the errors in those floats, which are only precise to 53 bits (around 15 decimal digits).
You can fix that by changing
c = pow(decimal.Decimal(1/5), decimal.Decimal(b))
to
c = pow(1 / decimal.Decimal(5), decimal.Decimal(b))
or
c = pow(decimal.Decimal(5), decimal.Decimal(-b))
Obviously, a similar change needs to be made to
c = pow(decimal.Decimal(1/239), decimal.Decimal(b))
You could make your code a lot more readable. For starters, you should put the stuff that calculates the arctan series into a function, rather than duplicating it for arctan(1/5) and arctan(1/239).
Also, you don't need to use Decimal for everything. You can just use simple Python integers for things like count and a. Eg, your calculation for a can be written as
a = (-1) ** count
or you could just set a to 1 outside the loop and negate it each time through the loop.
Here's a more compact version of your code.
import decimal
decimal.getcontext().prec = 60 #Setting precision
def arccot(n, terms):
base = 1 / decimal.Decimal(n)
result = 0
sign = 1
for b in range(1, 2*terms, 2):
result += sign * (base ** b) / b
sign = -sign
return result
pi = 16 * arccot(5, 50) - 4 * arccot(239, 11)
print(pi)
output
3.14159265358979323846264338327950288419716939937510582094048
The last 4 digits are rubbish, but the rest are fine.

Optimising iterative loop

I'm gradually moving from Matlab to Python and would like to get some advice on optimising an iterative loop.
This is how I am currently running the loop, and for info I've included the code that defines the variables.
nh = 2000
h = np.array(range(nh))
nt = 10000
wmin = 1
wmax = 10
hw = np.array(wmin + (wmax-wmin)*invlogit(randn(1,nh)));
sl = np.array(zeros((nh,1))+radians(40))
fa = np.array(zeros((nh,1))+radians(35))
c = np.array(zeros((nh,1))+4.4)
y = np.array(zeros((nh,1))+17.6)
yw = np.array(zeros((nh,1))+9.81)
ir = 0.028
m = np.array(zeros((nh,nt)));
m[:,49] = 0.1
z = np.array(zeros((nh,nt)))
z[:,0] = 0+(3.0773-0)*rand(nh,1).T
reset = np.array(zeros((nh,nt)))
fs = np.array(zeros((nh,nt)))
for t in xrange(0, nt-1):
fs[:,t] = (c.T+(y.T-m[:,t]*yw.T)*z[:,t]*(np.cos(sl.T)**2)*np.tan(fa.T))/(y.T*z[:,t]*np.sin(sl.T)*np.cos(sl.T))
reset[fs[:,t]<=1,t+1] = 1;
z[fs[:,t]<=1,t+1] = 0;
z[fs[:,t]>1,t+1] = z[fs[:,t]>1,t]+(ir/hw[0,fs[:,t]>1]).T
This is how I would optimise the code in Matlab, however it runs fairly slowly in python. I suspect there is a more pythonic way of doing this and would really appreciate a nudge in the right direction.
Many thanks!
Not specifically about the loop, you're doing a ton of extra work in calls that look like:
np.array(zeros((nh,nt)))
Just use:
np.zeros((nh,nt))
in its place. Additionally, you could replace:
h = np.array(range(nh))
with:
h = np.arange(nh)
Other comments:
You're calling np.sin(sl.T)*np.cos(sl.T) in every loop although, sl does not appear to be changing at all. Just calculate it once and assign it to a variable that you use in the loop. You do this in a bunch of your trig calls.
The expression
(c.T+(y.T-m[:,t]*yw.T)*z[:,t]*(np.cos(sl.T)**2)*np.tan(fa.T))/(y.T*z[:,t]*np.sin(sl.T)*np.cos(sl.T))
uses c, y, m, yw, sl, fa that do not change inside the loop. You could compute several subexpressions before the loop.
Also, most of those arrays contain one repeated value. You could compute with scalars instead:
sl = radians(40)
fa = radians(35)
c = 4.4
y = 17.6
yw = 9.81
Then, with precomputed subexpressions:
A = cos(sl)**2 * tan(fa) * (y - m*yw)
B = y*sin(sl)*cos(sl)
for t in xrange(0, nt-1):
fs[:,t] = (c + A[:,t]*z[:,t]) / (B*z[:,t])
less = fs[:,t]<=1
more = np.logical_not(less)
reset[less,t+1] = 1
z[less,t+1] = 0
z[more,t+1] = z[more,t]+(ir/hw[0,more]).T

Categories

Resources