Convert numpy int to matlab int - python

I'm calling a matlab function in python through matlab engine, and I'm having problems to pass the variables.
I have figured out how to pass some, but for this on I'm getting an error. should be a scalar int.
but when I pass it I got the error:
File
"C:\ProgramData\Anaconda3\lib\site-packages\matlab_internal\mlarray_utils.py",
line 90, in _normalize_size
if init_dims[0] == 0:
IndexError: tuple index out of range
The code works fine If I do not pass the modn variable, so I know that my problem is the conversion type to matlab of this variable.
this is the python code:
import numpy as np
import matlab
import matlab.engine
eng = matlab.engine.start_matlab()
eng.cd()
Nn = 30
x= 250*np.ones((1,Nn))
y= 100*np.ones((1,Nn))
z = 32.0
xx = matlab.double(x.tolist())
yy = matlab.double(y.tolist())
f=np.arange(start=0.1,stop=0.66,step=0.1)
modnv=np.concatenate((np.ones((Nn)),2*np.ones((Nn))))
count = 0
for fks in f:
fks=np.float(0)
modn = modnv[count]
modn = modn.astype(int)
modn = matlab.int8(modn)
Output = eng.simple_test(xx,yy,z,fks,modn,nargout=4)
A = np.array(Output[0]).astype(float)
B = np.array(Output[1]).astype(float)
C = np.array(Output[2]).astype(float)
D = np.array(Output[3]).astype(float)
count = count + 1
and this is the matlab function simple_test:
function [A,B,C,D] = simple_test(x,y,z,fks,modn)
if modn == 1
A = 3*x+2*y;
B = x*ones(length(x),length(x));
C = ones(z);
D = x*y';
else
A = 3*fks;
B = 3*x+2*y;
C = A+B;
D = x*y'
end
Does someone know how to overcome that?

Whenever you get IndexError: tuple index out of range error its mostly:
Probably one of the indexes is wrong.I suspect you mean to say [0] where you say [1] and [1] where you say [2]. Indexes are 0-based in Python.
you are passing an array to a function that was expecting a variadic sequence of arguments (eg '{}{}'.format([1,2]) vs '{}{}'.format(*[1,2])

Related

Solving multivariate equation for a subset of variables

I am using sympy to solve some equations and I am running into a problem. I have this issue with many equations but I will illustrate with an example. I have an equation with multiple variables and I want to solve this equation in terms of all variables but one is excluded. For instance the equation 0 = 2^n*(2-a) - b + 1. Here there are three variables a, b and n. I want to get the values for a and b not in terms of n so the a and b may not contain n.
2^n*(2-a) - b + 1 = 0
# Since we don't want to solve in terms of n we know that (2 - a)
# has to be zero and -b + 1 has to be zero.
2 - a = 0
a = 2
-b + 1 = 0
b = 1
I want sympy to do this. Maybe I'm just not looking at the right documentation but I have found no way to do this. When I use solve and instruct it to solve for symbols a and b sympy returns to me a single solution where a is defined in terms of n and b. I assume this means I am free to choose b and n, However I don't want to fix n to a specific value I want n to still be a variable.
Code:
import sympy
n = sympy.var("n", integer = True)
a = sympy.var("a")
b = sympy.var("b")
f = 2**n*(2-a) - b + 1
solutions = sympy.solve(f, [a,b], dict = True)
# this will return: "[{a: 2**(-n)*(2**(n + 1) - b + 1)}]".
# A single solution where b and n are free variables.
# However this means I have to choose an n I don't want
# to that I want it to hold for any n.
I really hope someone can help me. I have been searching google for hours now...
Ok, here's what I came up with. This seems to solve the type of equations you're looking for. I've provided some tests as well. Of course, this code is rough and can be easily caused to fail, so i'd take it more as a starting point than a complete solution
import sympy
n = sympy.Symbol('n')
a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')
d = sympy.Symbol('d')
e = sympy.Symbol('e')
f = sympy.sympify(2**n*(2-a) - b + 1)
g = sympy.sympify(2**n*(2-a) -2**(n-1)*(c+5) - b + 1)
h = sympy.sympify(2**n*(2-a) -2**(n-1)*(e-1) +(c-3)*9**n - b + 1)
i = sympy.sympify(2**n*(2-a) -2**(n-1)*(e+4) +(c-3)*9**n - b + 1 + (d+2)*9**(n+2))
def rewrite(expr):
if expr.is_Add:
return sympy.Add(*[rewrite(f) for f in expr.args])
if expr.is_Mul:
return sympy.Mul(*[rewrite(f) for f in expr.args])
if expr.is_Pow:
if expr.args[0].is_Number:
if expr.args[1].is_Symbol:
return expr
elif expr.args[1].is_Add:
base = expr.args[0]
power = sympy.solve(expr.args[1])
sym = expr.args[1].free_symbols.pop()
return sympy.Mul(sympy.Pow(base,-power[0]), sympy.Pow(base,sym))
else:
return expr
else:
return expr
else:
return expr
def my_solve(expr):
if not expr.is_Add:
return None
consts_list = []
equations_list = []
for arg in expr.args:
if not sympy.Symbol('n') in arg.free_symbols:
consts_list.append(arg)
elif arg.is_Mul:
coeff_list = []
for nested_arg in arg.args:
if not sympy.Symbol('n') in nested_arg.free_symbols:
coeff_list.append(nested_arg)
equations_list.append(sympy.Mul(*coeff_list))
equations_list.append(sympy.Add(*consts_list))
results = {}
for eq in equations_list:
var_name = eq.free_symbols.pop()
val = sympy.solve(eq)[0]
results[var_name] = val
return results
print(my_solve(rewrite(f)))
print(my_solve(rewrite(g)))
print(my_solve(rewrite(h)))
print(my_solve(rewrite(i)))

using jacobi method to solve laplace equation PYTHON

I am fairly new to python and am trying to recreate the electric potential in a metal box using the laplace equation and the jacobi method. I have written a code that seems to work initially, however I am getting the error: IndexError: index 8 is out of bounds for axis 0 with size 7 and can not figure out why. any help would be awesome!
from visual import*
from visual.graph import*
import numpy as np
lenx = leny = 7
delta = 2
vtop = [-1,-.67,-.33,.00,.33,.67,1]
vbottom = [-1,-.67,-.33,.00,.33,.67,1]
vleft = -1
vright = 1
vguess= 0
x,y = np.meshgrid(np.arange(0,lenx), np.arange(0,leny))
v = np.empty((lenx,leny))
v.fill(vguess)
v[(leny-1):,:] = vtop
v [:1,:] = vbottom
v[:,(lenx-1):] = vright
v[:,:1] = vleft
maxit = 500
for iteration in range (0,maxit):
for i in range(1,lenx):
for j in range(1,leny-1):
v[i,j] = .25*(v[i+i][j] + v[i-1][j] + v[i][j+1] + v[i][j-1])
print v
Just from a quick glance at your code it seems as though the indexing error is happening at this part and can be changed accordingly:
# you had v[i+i][j] instead if v[i+1][j]
v[i,j] = .25*(v[i+1][j] + v[i-1][j] + v[i][j+1] + v[i][j-1])
You simply added and extra i to your indexing which would have definitely been out of range

Variable changing by itself inside loop

I have a python for loop that seems to have a variable changing of its own accord inside the loop. My variables are defined as:
yhat = np.empty((1,len(prices)))
yhat[:] = nan
yhat = yhat.astype('float')
e = Q = yhat
P = R = np.matrix(np.zeros((2,2)))
B = np.empty((2,len(prices)))
B[:] = nan
B = np.matrix(B)
B[:,0] = 0
The loop is: (prices is a dataframe)
for t in xrange(0,len(prices),1):
if t > 0:
B[:,t] = B[:,t-1]
R = P+Vw
yhat[0,t] = x[t,:]*B[:,t]
print yhat[0,t]
Q[0,t] = x[t,:]*R*x[t,:].T + Ve
print yhat[0,t]
e[0,t] = y[t,0] - yhat[0,t]
print yhat[0,t]
K = (R*x[t,:].T)/Q[0,t]
B[:,t] = B[:,t]+K*e[0,t]
P = R - K*x[t,:]*R
I'm printing yhat because I've narrowed the anomaly in the code down to it. After set the value of yhat # t, it seems to change. When I run the code, it prints out:
0.0
0.001
20.438747
Additionally, I'm concerned about the subtraction for e[0,t] because for some reason the subtraction results in the value of yhat at that current moment?
Maybe I'm missing something blatantly obvious. I'm relatively new to python, and I switched over from MATLAB.
EDIT: x & y are also matrix objects. So all of the multiplications are matrix dot products.
e = Q = yhat won't create copies. They are instead additional references to the same object. Altering that object through either the e or Q names will reflect in those changes being visible through the yhat reference too.
So
yhat[0,t] = x[t,:]*B[:,t]
and
Q[0,t] = x[t,:]*R*x[t,:].T + Ve
and
e[0,t] = y[t,0] - yhat[0,t]
all operate on the same, single numpy array object, not on separate objects.
Use the numpy.copy() function to create independent new copies instead:
e, Q = np.copy(yhat), np.copy(yhat)

python why data type changed by def function?

Why num_r1(x) and num_r2(x) type numpy.ndarray, but num_r(t) is type float? How can I keep num_r(t) type as array?
def num_r(t):
for x in t:
if x>tx:
return num_r2(x)
else:
return num_r1(x)
Thank you!
The complete example is below
# -*- coding: utf-8 -*
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
import math
from pylab import *
#### physical parameters
c = 2.998*10**10
hp = 6.626*10**-27
hb = 1.055*10**-27
kb = 1.381*10**-16
g = 6.673*10**-8
me = 9.109*10**-28
mp = 1.673*10**-24
q = 4.803*10**-10 #gausi
sigT = 6.652*10**-25
# The evolution of the characteristic frequencies
p = 2.5
E52 = 1
epsB_r = 1
epse_r = 1
D28 = 1
n1 = 1.0
nu15 = 1*10**(-5)
r014 = 1
g42 = 1
delt12 =1
g4 = g42*10**2.5
E0 = E52*10**52
eta = g4
N0 = E0/(g4*mp*c**2)
p_tx = 3**(1./3)*2**(4./3)*mp**(-1./3)*c**(-5./3)
tx = p_tx*n1**(-1./3)*eta**(-8./3)
p_num_r1 = 2**(11./2)*7**(-2)*mp**(5./2)*me**(-3)*pi**(-1./2)*q*p_tx**(-6)*2**30*3**18*10**12
p_nuc_r1 = 2**(-33./2)*3**(-4)*10**(-4)*me*mp**(-3./2)*c**(-2)*sigT**(-2)*pi**(-1./2)*q
p_Fmax_r1 = 2**(15./2)*3**(9./2)*10**30*p_tx**(-3./2)*10**(-56)*me*mp**(1./2)*c**3*sigT*q**(-1)*2**(1./2)*3**(-1)
p_num_r2 = 2**(11./2)*7**(-2)*mp**(5./2)*me**(-3)*pi**(-1./2)*q*p_tx**(54./35)*(2**5*3**3*10**2)**(-54./35)
p_nuc_r2 = 2**(-13./2)*3**2*pi**(-1./2)*me*mp**(-3./2)*c**(-2)*sigT**(-2)*q*p_tx**(-74./35)*(2**5*3**3*10**2)**(4./35)
p_Fmax_r2 = 2**(1./2)*3**(-1)*pi**(-1./2)*me*mp**(1./2)*c**3*sigT*q**(-1)*10**(-56)
num_r1 = lambda t : p_num_r1*eta**18*((p-2)/(p-1))**2*epse_r**2*epsB_r**(1./2)*n1**(5./2)*t**6*E52**(-2)
nuc_r1 = lambda t : p_nuc_r1*eta**(-4)*epsB**(-3./2)*n1**(-3./2)*t**(-2)
Fmax_r1 = lambda t : p_Fmax_r1*N0**t**(3./2)*n1*eta**6*E52**(-1./2)*D28**(-2)*epsB_r**(1./2)
num_r2 = lambda t : p_num_r2*((p-2)/(p-1))**2*n1**(-74./35)*n1**(74./105)*eta**(592./105)*E52**(-74./105)
nuc_r2 = lambda t : p_nuc_r2*eta**(172./105)*t**(4./35)*n1**(-167./210)*epsB_r**(-3./2)
Fmax_r2 = lambda t : N0*eta**(62./105)*n1**(37./210)*epsB_r**(1./2)*t**(-34./35)*D28**(-2)
def fspe(t,u):
if num_r(t)<nuc_r(t):
return np.where(u<num_r(t),(u/num_r(t))**(1./3)*Fmax_r(t),np.where(u<nuc_r(t),(u/num_r(t))**(-(p-1.)/2)*Fmax_r(t),(u/nuc_r(t))**(-p/2)*(nuc_r(t)/num_r(t))**(-(p-1.)/2)*Fmax_r(t)))
else:
return np.where(u<nuc_r(t),(u/nuc_r(t))**(1./3)*Fmax_r(t),np.where(u<num_r(t),(u/nuc_r(t))**(-1./2)*Fmax_r(t),(u/num_r(t))**(-p/2)*(num_r(t)/nuc_r(t))**(-1.2)*Fmax_r(t)))
def num_r(t):
for x in t:
if x>tx:
return num_r2(x)
else:
return num_r1(x)
def nuc_r(t):
for x in t:
if t>tx:
return nuc_r2(x)
else:
return nuc_r1(x)
def Fmax_r(t):
for x in t:
if t>tx:
return Fmax_r2(x)
else:
return Fmax_r1(x)
i= np.arange(-4,6,0.1)
t = 10**i
dnum = [math.log10(mmm) for mmm in num_r(t)]
dnuc = [math.log10(j) for j in nuc_r(t)]
nu_obs = [math.log(2.4*10**17,10) for a in i]
plt.figure('God Bless: Observable Limit')
plt.title(r'$\nu_{obs}$ and $\nu_c$ and $\nu_m$''\nComparation')
plt.xlabel('Time: log t')
plt.ylabel(r'log $\nu$')
plt.axvline(math.log10(tx))
plt.plot(i,nu_obs,'.',label=r'$\nu_{obs}$')
plt.plot(i,dnum,'D',label=r'$\nu_m$')
plt.plot(i,dnuc,'s',label=r'$\nu_c$')
plt.legend()
plt.grid(True)
plt.savefig("nu_obs.eps", dpi=120,bbox_inches='tight')
plt.show()
But thereÅ› a Error
TypeError Traceback (most recent call last)
<ipython-input-250-c008d4ed7571> in <module>()
95 i= np.arange(-4,6,0.1)
96 t = 10**i
---> 97 dnum = [math.log10(mmm) for mmm in num_r(t)]
TypeError: 'float' object is not iterable
You should write your function as:
def num_r_(x):
if x > tx:
return num_r2(x)
else:
return num_r1(x)
And then pass it through np.vectorize to lift it from float to float to np.array to np.array
num_r = np.vectorize(num_r_)
From Efficient evaluation of a function at every cell of a NumPy array
And then when you use it in:
dnum = [math.log10(mmm) for mmm in num_r(t)]
You should rather do:
dnum = np.log10(num_r(t))
That is to say don't use the functions from the math module. Use those from the np module as they can take np.array as well as float.
As:
i = np.arange(-4,6,0.1)
t = 10**i
results in t being a np.array
So i is an array (arange); so is t (a math expression of i).
def num_r(t):
for x in t:
if x>tx:
return num_r2(x)
else:
return num_r1(x)
You iterate on t. x is an element of t. You test it and pass it through num_r2 or num_r1, and return immediately. So only the 1st element t is being processed. Thus the error - num_r returns one value, not an array.
You need to write num_r in a way that processes all the values of t, not just the first. A simple, crude way is
def num_r(t):
result = []
for x in t:
if x>tx:
value = num_r2(x)
else:
value = num_r1(x)
result.append(value)
# result = np.array(result)
return result
Now num_r should return a list the same length as t, and can be use in the list comprehension
[math.log10(mmm) for mmm in num_r(t)]
num_r could be written as a list comprehension:
[(num_r2(x) if x>tx else num_r1(x)) for x in t]
You could have it return an array instead of a list, but as long as you are using it in the list comprehension, there's no need. A list is just fine.
If it did return an array, then you could replace the list comprehension with a numpy log operation, e.g.
np.log10(num_r(t))
If num_r1 and num_r2 are written so they can take an array (looks off hand like they are, but I haven't tested), you could write
def num_r(t):
ind = t>tx
result = np.zeros_like(t)
result[ind] = num_r2(t[ind])
result[~ind] = num_r1(t[~ind])
return result
The idea is to find a mask of a values in t that are >tx, and pass all those through num_r2 at once; similarly for num_r1; and collect the values in the correct slots of result. The result is an array that can be passed to np.log10. This should be quite a bit faster than iterating on t, or using np.vectorize.
There may be some errors in my suggestions, since I did not test them in an script or interpreter. But the underlying ideas should be correct and set you on the right path.

Matlab to Python conversion - Can't assign to function call

I have recently been trying to convert a piece of Matlab code into Python code.
I have made most of the changes that I need to however, the issue I am having is the line where it says:
y(index(m)) = 1-x(index(m));
I get the error:
"Can't assign to function call"
However I am not sure how to restructure it in order to remove this error.
I have had a look around and people mention "get item" and "set item" however I have tried to use them, but I can't get them to work (probably because I can't figure out the structure)
Here is the full code:
import numpy
N = 100;
B = N+1;
M = 5e4;
burnin = M;
Niter = 20;
p = ones(B,Niter+1)/B;
hit = zeros(B,1);
for j in range(1,Niter):
x = double(rand(1,N)>0.5);
bin_x = 1+sum(x);
index = ceil(N*rand(1,M+burnin));
acceptval = rand(1,M+burnin);
for m in range(1,M+burnin):
y = x;
y(index(m)) = 1-x(index(m));
bin_y = 1+sum(y);
alpha = min(1, p(bin_x,j)/p(bin_y,j) );
if acceptval(m)<alpha:
x = y; bin_x = bin_y;
end
if m > burnin: hit(bin_x) = hit(bin_x)+1; end
end
pnew = p[:,j];
for b in range(1,B-1):
if (hit(b+1)*hit(b) == 0):
pnew(b+1) = pnew(b)*(p(b+1,j)/p(b,j));
else:
g(b,j) = hit(b+1)*hit(b) / (hit(b+1)+hit(b));
g_hat(b) = g(b,j)/sum(g(b,arange(1,j)));
pnew(b+1) = pnew(b)*(p(b+1,j)/p(b,j))+((hit(b+1)/hit(b))^g_hat(b));
end
end
p[:,j+1] = pnew/sum(pnew);
hit[:] = 0;
end
Thanks in advance
The round brackets () indicate a function. For indexing you need [] square brackets - but that is only the first of many, many errors... I am currently going through line by line, but it's taking a while.
This code at least runs... you need to figure out whether the indexing is doing what you are expecting since Python arrays are indexed from zero, and Matlab arrays start at 1. I tried to fix that in a couple of places but didn't go through line by line - that's debugging.
Some key learnings:
There is no end statement... just stop indenting
When you import a library, you need to reference it (numpy.zeros, not zeros)
Lists are indexed from zero, not one
Indexing is done with [], not ()
Creating an array of random numbers is done with [random.random() for r in xrange(N)], not random(N).
... and many other things you will find as you look through the code below.
Good luck!
import numpy
import random
N = int(100);
B = N+1;
M = 5e4;
burnin = M;
Niter = 20;
p = numpy.ones([B,Niter+1])/B;
hit = numpy.zeros([B,1]);
g = numpy.zeros([B, Niter]);
b_hat = numpy.zeros(B);
for j in range(1,Niter):
x = [float(random.randint(0,1)>0.5) for r in xrange(N)];
bin_x = 1+sum(x);
index = [random.randint(0,N-1) for r in xrange(int(M+burnin))];
#acceptval = rand(1,M+burnin);
acceptval = [random.random() for r in xrange(int(M+burnin))];
for m in range(1,int(M+burnin)):
y = x;
y[index[m]] = 1-x[index[m]];
bin_y = 1+sum(y);
alpha = min(1, p[bin_x,j]/p[bin_y,j] );
if acceptval[m]<alpha:
x = y; bin_x = bin_y;
if m > burnin:
hit[bin_x] = hit[bin_x]+1;
pnew = p[:,j];
for b in range(1,B-1):
if (hit[b+1]*hit[b] == 0):
pnew[b+1] = pnew[b]*(p[b+1,j]/p[b,j]);
else:
g[b,j] = hit[b+1]*hit[b] / [hit[b+1]+hit[b]];
g_hat[b] = g[b,j]/sum(g[b,numpy.arange(1,j)]);
pnew[b+1] = pnew[b]*(p[b+1,j]/p[b,j])+((hit[b+1]/hit[b])^g_hat[b]);
p[:,j+1] = pnew/sum(pnew);
hit[:] = 0;

Categories