I am converting matlab file to python code. my matlab file is :
function [q,len] = curve_to_q(p)
[n,N] = size(p);
for i = 1:n
v(i,:) = gradient(p(i,:),1/(N));
end
len = sum(sqrt(sum(v.*v)))/N;
v = v/len;
for i = 1:N
L(i) = sqrt(norm(v(:,i)));
if L(i) > 0.0001
q(:,i) = v(:,i)/L(i);
else
q(:,i) = v(:,i)*0.0001;
end
end
converted code is :
from __future__ import division
import numpy as np
from scipy.io import loadmat,savemat
import os
def curve_to_q(p):
n, N = p.shape # nargout=2
for i in range(1, (n +1)):
v[(i -1), :] = np.gradient(p[(i -1), :], 1 / (N))
len_ = np.sum(np.sqrt(np.sum(v.np.dot(v)))) / N
v = v / len_
for i in range(1, (N +1)):
L[(i -1)] = sqrt(norm(v[:, (i -1)]))
if L[(i -1)] > 0.0001:
q[:, (i -1)] = v[:, (i -1)] / L[(i -1)]
else:
q[:, (i -1)] = v[:, (i -1)] * 0.0001
return q, len_
But, there seems to be problem in
len_ = np.sum(np.sqrt(np.sum(v.np.dot(v)))) / N
and
L[(i -1)] = sqrt(norm(v[:, (i -1)]))
how can i make it proper conversion to python?
2 Answers 2
Working with numpy, it is better to initialise all arrays as numpy arrays rather than python arrays (lists of lists) and then converting to numpy at the time of execution. So for the first step I'd put in v = np.zeros(n, N) to initialise. This should fix your second problem.
The next step is to make your code more readable. Remove N+1/i-1, etc. L doesn't need to be a list - only the current value is ever used, so change it to a local variable rather than a list.
In matlab: v.*v is not the dot product, it is the element by element multiplication of the two arrays. Further, when you try to take the dot product of v with itself, v is not square, so it won't work. However, we can use the dot product with the transpose to simplify this step.
The code below should help. The first sum in the matlab code sums across the 'first array dimension' (I forget which one this is) - so you'll have to check that v_squared_sum has the same dimensions in both languages.
def curve_to_q(p):
n, N = p.shape # nargout=2
v = np.zeros((n, N))
for i in range(n):
v[i, :] = np.gradient(p[i, :], 1 / N)
v_squared_sum = v.dot(v.transpose()) # 1 x (n or N) array
len_ = np.sum(np.sqrt(v_squared_sum)) / N
v = v / len_
for i in range(N):
L = sqrt(norm(v[:, i]))
q[:, i] = v[:, i] / max(L, 0.0001)
return q, len_
Comments
Your first problem is that in Matlab, sum sums over the last dimension by default, while in numpy, np.sum sums over the flattened array by default.
Matlab
>> sum([5,5,5;5,5,5])
ans =
10 10 10
Python:
>>> np.sum([[5,5,5],[5,5,5]])
30
You would need something like this in python:
>>> np.sum([[5,5,5],[5,5,5]], axis=0)
array([10, 10, 10])
The second problem is that you need np.sqrt and np.norm, not sqrt and norm.
vanywhere incurve_to_q, which could be causing problems. Same forL. Ifvis an array, you should be using*, notnp.dot, and ifvis a matrix, you should be usingnp.multiply(because you want.*, which is elementwise multiplication, not matrix multiplication).v.np.dottov.dot