Struct to cell (or matrix) in Matlab - matlab

I have a structure with fields ID,Coor,Misc,Conn. ID and Misc are doubles, however, Coor is a 1x3 vector and Conn is a 1xn vector (where n can theoretically be from 0 to inf).
Point(x).ID = [x]
Point(x).Coordinate = [xPos yPos zPos]
Point(x).Misc = [randomDouble]
Point(x).Conn = [someVectorOfNumbers]
I would like to have this mapped on a cell array, without using a FOR loop.
An example of the output:
'ID xPos yPos zPos Misc Conn'
1 0 0 0 0 '0 1 2'
2 1 1 1 1 ''
...
x x x x x '2'
Notice that Point.Conn, its vector of numbers gets converted into a string.
The issues that I am having is breaking up Point.Coordinate into its three elements, and converting Point.Conn into a string.
I feel like this can be done using struct2Cell and then changing the nesting level. I'm just not exactly sure how to do that.

First make some example data:
n = 10;
ID = num2cell(randperm(n)');
Coordinate = mat2cell(randn(n, 3), ones(n,1));
Misc = num2cell(randn(n,1));
Conn = arrayfun(#randperm, randperm(n), 'UniformOutput', 0)';
Point = struct('ID', ID, 'Coordinate', Coordinate, 'Misc', Misc, 'Conn', Conn);
Now inspect it:
>> Point
Point =
10x1 struct array with fields:
ID
Coordinate
Misc
Conn
>> Point(1)
ans =
ID: 7
Coordinate: [-0.0571 -1.1645 2.4124]
Misc: 0.0524
Conn: [3 2 1]
Now use arrayfun() to sweep through the elements of structure array Point. We define a generic function x to operate on each element of Point, formatting the row like you described:
Point_cell = arrayfun(#(x) [num2cell([x.ID x.Coordinate x.Misc]) num2str(x.Conn)], Point, 'UniformOutput', 0);
Point_cell = vertcat(Point_cell{:})
Now inspect the output:
ans =
[ 7] [-0.0571] [-1.1645] [ 2.4124] [ 0.0524] '3 2 1'
[ 5] [ 0.2918] [ 0.4948] [ 0.7402] [-1.9539] '1 2'
[ 3] [-0.6146] [-1.2158] [ 0.3097] [ 0.5654] '3 4 1 2'
[10] [-0.0136] [ 1.5908] [-0.5420] [ 0.0778] [1x25 char]
[ 2] [ 0.4121] [ 0.5265] [ 0.1223] [ 0.0807] [1x22 char]
[ 1] [-0.9371] [ 0.2648] [ 0.9623] [ 0.7947] '1 2 5 4 3'
[ 4] [ 0.8352] [-0.3936] [-0.2540] [ 1.0437] '6 2 3 7 4 1 5'
[ 8] [ 1.0945] [-2.1763] [ 1.8918] [ 0.8022] '1'
[ 6] [ 0.3212] [-1.1957] [-1.2203] [-0.4688] [1x37 char]
[ 9] [ 0.0151] [ 0.3653] [-0.3762] [-0.0466] '3 5 4 2 6 1'
Couldn't tell from your question, but if you want all the numeric fields as an array inside a single cell, that is an easy tweak to do. Good luck!

Here is a slightly different solution using STRUCT2CELL:
%# build a sample array of structures
id = num2cell((1:10)',2); %'
coords = num2cell(rand(10,3),2);
misc = num2cell(rand(10,1),2);
conn = arrayfun(#(n)randi(5,[1 n]), randi([0 6],[10 1]), 'UniformOutput',false);
p = struct('ID',id, 'Coordinate',coords, 'Misc',misc, 'Conn',conn);
%# convert to cell array
h = fieldnames(p)'; %'
X = struct2cell(p)'; %'
%# split 'coords' field into 3 separate columns
h2 = {'xPos' 'yPos' 'zPos'};
X2 = num2cell( cell2mat(X(:,2)) );
%# convert 'conn' field to string
X4 = cellfun(#num2str, X(:,4), 'UniformOutput',false);
X4 = regexprep(X4, '[ ]+', ' '); %# clean multiple spaces as one
%# build final cell array with headers
C = [h(1) h2 h(3:4) ; X(:,1) X2 X(:,3) X4]
The result:
>> C
C =
'ID' 'xPos' 'yPos' 'zPos' 'Misc' 'Conn'
[ 1] [0.78556] [ 0.46707] [0.66281] [ 0.46484] '3'
[ 2] [0.51338] [ 0.6482] [0.33083] [ 0.76396] '2 1 2 5 1 2'
[ 3] [ 0.1776] [0.025228] [0.89849] [ 0.8182] '1 3 1 5'
[ 4] [0.39859] [ 0.84221] [0.11816] [ 0.10022] '1 1 2'
[ 5] [0.13393] [ 0.55903] [0.98842] [ 0.17812] '3 1 5 2 2 1'
[ 6] [0.03089] [ 0.8541] [0.53998] [ 0.35963] ''
[ 7] [0.93914] [ 0.34788] [0.70692] [0.056705] '2 1 3 4 4'
[ 8] [0.30131] [ 0.44603] [0.99949] [ 0.52189] '1 1 4 5 3'
[ 9] [0.29553] [0.054239] [0.28785] [ 0.33585] '1 5 2'
[10] [0.33294] [ 0.17711] [0.41452] [ 0.17567] '2'
where for example the second structure was:
>> p(2)
ans =
ID: 2
Coordinate: [0.51338 0.6482 0.33083]
Misc: 0.76396
Conn: [2 1 2 5 1 2]

Related

How to get from MNA system of equations to state-space [A,B,C,D] mimo in MATLAB?

I want to programatically generate state-space [A B C D] system from a generated MNA (modified nodal analysis) system of equations. I don't know which MATLAB functions to call.
I use the SCAM link script from Erik Cheever to generate the system of equations.
I made file example3.cir link which is a spice RLC circuit with input source Vs.
I also tried netlist2linss link github but it is not in laplace domain and it does not work correctly.
example3.cir:
R1 2 1 R
C1 3 0 C
L1 2 3 L
Vs 1 0 V
>> fname = 'example3.cir'; scam; system_of_eqns = [Z == A*X]
Solved variables:
v_1
v_2
v_3
I_Vs
system_of_eqns =
0 == I_Vs + v_1/R1 - v_2/R1
0 == v_2*(1/R1 + 1/(L1*s)) - v_1/R1 - v_3/(L1*s)
0 == v_3*(C1*s + 1/(L1*s)) - v_2/(L1*s)
Vs == v_1
>> [A_,b_] = equationsToMatrix(system_of_eqns, X)
A_ =
[ -1/R1, 1/R1, 0, -1]
[ 1/R1, - 1/R1 - 1/(L1*s), 1/(L1*s), 0]
[ 0, 1/(L1*s), - C1*s - 1/(L1*s), 0]
[ -1, 0, 0, 0]
b_ =
0
0
0
-Vs
expected (capacitor voltage as output):
A =
[ 0, 1/C1 ]
[ -1/L1, -R/L1 ]
B =
[ 0, 1/L1 ]
C =
[ 1, 0 ]
D =
[ 0 ]
states = [sVC1 sIL1]
input = [ Vs ]
I found a solution in python called lcapy:
https://github.com/mph-/lcapy

How to insert a column of characters to a matrix?

I'd like to insert a column of character to a matrix in MATLAB.
For example, we want to reach from first matrix to the second matrix:
first_matrix = [2 3; 4 5; 1 7]
second_matrix = [c 2 3; c 4 5; c 1 7]
In fact the reason is that, I have a output.txt file from a software. In that file, I should select a matrix in it, and change matrix column order. After doing this, i.e. reach to first_matrix, the output in form of second_matrix should be used in another software. So, finally I should save it in a text file format for second software.
You cannot do with this numeric arrays. The possible ways to do this are:
Using a categorical array i.e.
>> second_matrix = [num2cell(repmat('c',3,1)) categorical(first_matrix)]
ans =
3×3 categorical array
c 2 3
c 4 5
c 1 7
Using a character array i.e.
>> second_matrix = [repmat('c ',3,1) num2str(first_matrix)]
second_matrix =
3×7 char array
'c 2 3'
'c 4 5'
'c 1 7'
Using a string array (requires ≥ R2016b) i.e.
>> second_matrix = [repmat("c",3,1) first_matrix] %in ≥ R2017a
% second_matrix = [repmat(string('c'),3,1) first_matrix] %in ≥ R2016b
second_matrix =
3×3 string array
"c" "2" "3"
"c" "4" "5"
"c" "1" "7"
Using a cell array i.e.
>> second_matrix = [num2cell(repmat('c',3,1)) num2cell(first_matrix)]]
second_matrix =
3×3 cell array
{'c'} {[2]} {[3]}
{'c'} {[4]} {[5]}
{'c'} {[1]} {[7]}
Using a symbolic array (requires Symbolic Math Toolbox) i.e.
>> second_matrix = [repmat(sym('c'),3,1) first_matrix]
second_matrix =
[ c, 2, 3]
[ c, 4, 5]
[ c, 1, 7]

How to perform cartesian product in PDL

I want to take an arbitrary 1D vector a = [k] and b = [m] and form the matrix of ordered pairs c = [2 x k x m] such that $c->(:,(i),(j)) = [ $a->(i), $b->(j) ]. I.e. the set of all ordered pairs of the elements in a and b a.k.a the cartesian product.
Of course I could use a loop and the [glue] function to accomplish this, but that isn't in the spirit of Perl/PDL. Is there a fancy method that involves slices, dummy dimensions, and glue that gets me there?
Also, using Math::Cartesian::Product (as answered here: In Perl, how can I get the Cartesian product of multiple sets? is cheating! :3 I want straight perl/PDL and hopefully learn something in the process.
I got something that meets my criteria:
my $a = pdl 1,2,3,4;
my $b = pdl 5,6,7;
print "a = $a\n";
print "b = $b\n";
print "dummy dimensioned:\n";
$a = $a->dummy(0,$b->dim(0));
print "a".$a->shape." = $a\n";
$b = $b->dummy(0, $a->dim(1))->transpose;
print "b".$b->shape." = $b\n";
print "Glued together:\n"
my $c = $a->dummy(0,1)->glue(0, $b->dummy(0,1));
print "c".$c->shape." = $c\n";
a = [1 2 3 4]
b = [5 6 7]
dummy dimensioned:
a[3 4] =
[
[1 1 1]
[2 2 2]
[3 3 3]
[4 4 4]
]
b[3 4] =
[
[5 6 7]
[5 6 7]
[5 6 7]
[5 6 7]
]
Glued together:
c[2 3 4] = [[[1 5][1 6][1 7]][[2 5][2 6][2 7]][[3 5][3 6][3 7]][[4 5][4 6][4 7]]]

Append n x 1 vector to n x 1 cell array

I'm trying to append [1 2.2] to {'foo' 'ba'} and get:
'foo' 'ba'
1 2.200000
I'm nearly there:
>> A = {'foo' 'ba'}
A =
1×2 cell array
'foo' 'ba'
>> b = [1 2.2]
b =
1.000000000000000 2.200000000000000
>> [A;b]
Error using vertcat
Dimensions of matrices being concatenated are
not consistent.
>> [A;num2cell(b)]
ans =
2×2 cell array
'foo' 'ba'
[ 1] [2.200000000000000]
How to get rid of the []?
[A;num2cell(b)] is the correct implementation.
You can try doing
[A(1);b(1)]
ans =
'foo'
[ 1]
Notice the vector b element 1 represented as [ 1] which are equalivalent.
A = {'foo' 'ba'} ;
b = {'1' '2.2'} ;
[A ;b]
or
vertcat(A,b)

Instruction inside a While Loop Matlab

What does this instruction vector=[vector,sum(othervector)] does in matlab inside a while loop like:
vector=[];
while a - b ~= 0
othervector = sum(something') %returns a vector
vector=[vector,sum(othervector)]; %it keeps a new vector?
...
end
vector=vector./100
Executing a = [a,b] means append b to a, thus vector will eventually be a matrix where each column is the row-wise sum of something'.
More concretely: suppose something' is this matrix:
something' = [ 1, 2; 3, 4 ];
Then sum(something') is:
othervector = [ 3 ; 7 ]
And initially vector is empty, so this sets vector to
vector = [ 3 ; 7 ]
Suppose we repeat with a new something' consisting of
[ 5, 5; 5, 6 ]
Then sum(something') is:
othervector = [ 10; 11 ]
And now we augment this to vector using vector = [vector, sum(othervector)]:
vector = [ vector, [10; 11] ] = [ 3, 10 ; 7, 11 ]