MATLAB - accessing python lists and tuples - matlab

I have a python function, Foo, which returns a tuple of 3 lists. Each list contains points I would like to manipulate and plot in matlab. Current I can retrieve my data with
data = py.Foo.main(args)
Plotting the output proved difficult. Matlab sees "data" as a python object. I was previously in a rush and my quick work around was
function [r] = convertToVector(c)
%make sure everything is numeric so I can plot it
r = [];
for i = 1:length(c)
if isnumeric(c{i})
r = [r c{i}];
end
end
filler = data.cell()
a = convertToVector(filler{1}.cell())
b = convertToVector(filler{1}.cell())
c = convertToVector(filler{1}.cell())
This works okay but for c I have something like
filler.cell{3}.cell = [0] [-1] [-1] [-1] [0.22] [0.13] [0.08]
When I run convertToVector everything is either 0 or -1. I have no idea what is going on. If I play around in the console I can get something like
r = [];
z = filler.cell{3}.cell;
r = [r z{1}] >>> r = 0
r = [r z{2}] >>> r = 0 -1
r = [r z{5}] >>> r = 0 -1 0
Why is this happening? If I replace z{1} z{2} z{5} with 0 -1 0.22 respectively, I get the results I would expect: r = 0 -1 0.22. I don't use matlab regularly and I have no idea what may cause this. I was trying to plug the results of an analysis done in python into a pre-existing matlab gui, otherwise I would avoid interfacing the two as such.
Edit: Under further inspection utilizing whos r the class is int64 when adding z{1} to z{4} first and double when adding z{5} first. The class then changes from double to int64 if I add z{1} to z{4}

As per your edit, it seems the problem is that the initial integers in each cell (which are stored as ints or maybe numpy.uint64 types in python) are not automatically cast to double, and this seems reasonable. If you concatenate doubles to the uint64 array, the doubles will be cast to uint64 and not the other way around. This is only surprising since MATLAB very heavily defaults to using doubles whenever possible, so you might not expect this.
Simple python-free demonstration:
a = uint64([3, 4, 5]);
b = [a, 6];
c = [b, 7.3];
after this all three arrays will have uint64 class. Well, the example is a bit redundant, since class(6) is double, so if there was any typecasting, it would've already happened for b.
The solution is simple: explicitly cast to double in your function,
function [r] = convertToVector(c)
%make sure everything is numeric so I can plot it
r = [];
for i = 1:length(c)
if isnumeric(c{i})
r = [r double(c{i})]; %// only change here
end
end

Related

Vectorized function as output of matlabFunction

I am trying to automatize a process in MATLAB. I have a symbolic function that has to be converted into an anonymous function.
Basically, I have something like this:
syms x y z t
var = [x y z t];
f = x.^2+y;
gf = gradient(f, var);
gf_fun = matlabFunction(gf, 'vars', {var});
giving as output
gf_fun =
function_handle with value:
#(in1)[in1(:,1).*2.0;1.0;0.0;0.0]
Now, I'd like to evaluate this gf_fun in several points at a time, but, of course, I got strange results, due to how gf_fun is written. For example, if I want to evaluate gf_fun in 6 (different) points simultaneously, what I get is
rng('deafult')
vv = ones(6,4);
gf_fun(vv)
ans =
1.3575
1.5155
1.4863
0.7845
1.3110
0.3424
1.0000
0
0
instead of a matrix with dimensions 4x6, with each colomn being the evaluation of a single point.
I know that a workaround will be the use of a for loop, that is
results = zeros(4,6);
for i = 1:6
results(:,i) = gf_fun(vv(i,:));
end
but I must avoid it due to code performances reasons.
Is there a way to automatize all the process, having a matrix as output of gf_fun while evaluating different point at a time? So, basically, there is a simple way to replace the 0.0 and 1.0 in gf_fun with a more general zeros(size(in1)) and ones(size(in1)) automatically?
Thank you for you help!

How to avoid Matlab to convert doubles to integers while putting those doubles to a vector?

Hi I am trying to put double values into a vector but when I display this vector, I see that double values I put inside are converted to integers. How can I avoid this?
I checked the values of teta and they are as expected (ie. 1.802, 1.688), but in the matrix x, the values are all 1's.
SerialPort = 'COM23';
s = serial(SerialPort, 'BaudRate', 115200);
fopen(s);
n = 1;
while n<200
dis = fscanf(s,'d',2);
ang = fscanf(s,'d',3);
intDis = str2double(dis);
intAng = str2double(ang);
teta = pi/6 +(intAng-100)*pi/300;
x(n) = teta
y(n) = intDis;
n = n+1;
end
%polar(x,y)
fclose(s);
delete(s);
clear s;
The only way this can happen is if x was declared as an integer (or maybe logical?) before the script started. You should always initialize all variables, always, to avoid unexpected errors: add x=[]; to your script before the loop.
But your loop runs exactly 200 iterations, so you know the size x will have at the end. You can preallocate:
x = zeros(200,1);
I also recommend that you look into the syntax of the for loop, as that would be simpler in this case than while.

Why is this for loop giving me an error?

So I am trying to go through a for loop that will increment .1 every time and will do this until the another variable h is less than or equal to zero. Then I am suppose to graph this h variable along another variable x. The code that I wrote looks like this:
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
h(t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
The Error that I keep getting when running this code says "Attempted to access h(0); index must be a positive integer or logical." I don't understand what exactly is going on in order for this to happen. So my question is why is this happening and is there a way I can solve it, Thank you in advance.
You're using t as your loop variable as well as your indexing variable. This doesn't work, because you'll try to access h(0), h(0.1), h(0.2), etc, which doesn't make sense. As the error says, you can only access variables using integers. You could replace your code with the following:
t = 0:0.1:12;
for i = 1:length(t)
% use t(i) instead of t now
end
I will also point out that you don't need to use a for loop to do this. MATLAB is optimised for acting on matrices (and vectors), and will in general run faster on vectorised functions rather than for loops. For instance, your equation for h could be replaced with the following:
O = 20;
v = 200;
g = 32.2;
t = 0:0.1:12;
h = v * t * sin(O) - 0.5 * g * t.^2;
The only difference is that you have to use the element-wise square (.^2) rather than the normal square (^2). This means that MATLAB will square each element of the vector t, rather than multiplying the vector t by itself.
In short:
As the error says, t needs to be an integer or logical.
But your t is t=0:0.1:12, therefore a decimal value.
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
idx_t = 1:numel(t);
h(idx_t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(idx_t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
Look this question's answer for more options: Subscript indices must either be real positive integers or logical error

classification with four classes by matlab

I have a classification problem with four classes of input vector.The four classes are
A = [1 , 1; 1 ,2];
B = [2,2; -1,0];
C = [-1,-2;2,1];
D = [-1,-2; -1,-2];
I wan Implement this problem by Matlab, I Use this code :
C = [-1,-2;2,1];
A = [1 , 1; 1 ,2];
B = [2,2; -1,0];
D = [-1,-2; -1,-2];
hold on
grid on
plot(A(1,:),A(2,:),'bs')
plot(B(1,:),B(2,:),'r+')
plot(C(1,:),C(2,:),'go')
plot(D(1,:),D(2,:),'m*')
a = [0 1]';
b = [1 1]';
c = [1 0]';
d = [0 0]';
P = [A B C D];
T = [repmat(a,1,length(A)) repmat(b,1,length(B)) repmat(c,1,length(C)) repmat(d,1,length(D)) ];
net = perceptron;
E = 1;
net.adaptParam.passes = 1;
linehandle = plotpc(net.IW{1},net.b{1});
n = 0;
while (sse(E))
n = n+1;
[net,Y,E] = adapt(net,P,T);
linehandle = plotpc(net.IW{1},net.b{1},linehandle);
drawnow;
end
but My Code does'nt work I have No idea why, please Help me....
As has been suggested by thewaywewalk, the trouble is your while-loop and the fact that you do not provide an adequate check for the statement you wish to evaluate.
Replace your while-statement with these two lines:
ACCEPTABLE_ERROR = 3.0;
while (sse(E)>ACCEPTABLE_ERROR)
And you should see your script terminate after three iterations. You can play with the ACCEPTABLE_ERROR variable to check which solution works best for you. If you set it too small, your while loop will not exit, because the statement will not be false.
An explanation to your original while-statement:
All you ever evaluated if sse(e) returned a results - which it did in each case. That's why it never stopped.
To the question of sse requires more than one input argument:
That depends on what input arguments you provide.
The documentation says:
perf = sse(net,t,y,ew) takes these input arguments and optional function parameters,
net: Neural network
t: Matrix or cell array of target vectors
y: Matrix or cell array of output vectors
ew: Error weights (default = {1})
and returns the sum squared error.
However, it is not necessary, to provide the error weights, ew, as the source code reveals:
Only the first three arguments are required. The default error weight is {1}, which weights the importance of all targets equally.
In your case you should, based on the documentation, call sse like this:
sse(net,T,Y)
Without being mentioned in the documentation (or I haven't found it), this is equivalent to what you have done, by providing simply the network errors, E as provided from adapt:
sse(E)
Both give the same results.

how to Convert Matlab fft function to cvDft in opencv

I'm Very new to opencv.I need to convert the code from matlab to opencv.i have problem with use fft in matlab.i have a one dimensional matrix a.and i'm going apply fft in that as given below.
a = [0;0;0;0;0;0;0;0;0.09707;0.0998;0.1202;-0.1606;-0.0913;0.1523;0.1288];
c = abs(fft(a,15));
c >> 0.3463
0.1056
0.3608
0.5705
0.4232
0.2407
0.1486
0.1488
0.1488
0.1486
0.2407
0.4232
0.5705
0.3608
0.1056
C is my result,which i got from matlab.while i'm going to use cvDFT for this one the results are differnt.please help me with some example..my c code is given below...
CvMat* fftin = cvCreateMat(nn,1,CV_64FC2);
CvMat* fftout = cvCreateMat(nn,1,CV_64FC2);
cvZero(b); ////consider a hav the value of mat b is empty for imgin
cvMerge(a,b,NULL,NULL,fftin);
cvDFT(fftin,fftout,CV_DXT_FORWARD,0);
cvSplit(fftout,out_real,out_img,0,0);
for (int i = 0;i<out_real->rows;i++)
{
double val11= cvGetReal2D(out_real,i,0);
double val12= cvGetReal2D(out_img,i,0);
val11 = abs(val11);
val12 = abs(val12);
printf("DFT value is:%f %f\n",val11,val12);
cvSetReal2D(C_out,i,0,val11);
}
In your first example, you seem to be printing the magnitude of each complex value in the result. But in your second example you seem to be printing the absolute value of each component of the complex values (e.g. X and Y instead of the length or hypotenuse).