Add Object to Array in Matlab - arrays

I'm new to matlab and I can't add an object to an array:
%g is a transfer function
h = bodeplot(g);
% class('h') prints 'resppack.bodeplot'
a = zeros(2,1);
a(1,1) = h;
% I get the error: Conversion to double from resppack.bodeplot is not possible.
This happens because my matrix 'a' is of type double while 'h' isn't.
How can I define an array of type 'resppack.bodeplot'?
resppack.bodeplot doesn't have an 'empty' method...

The problem here, i s that you create an array of doubles, and you want to store other things.
You can not initialize the array and start adding objects like this:
my-array(1) = something
my-array(2) = something-2
...
new-array(1) = h
new-array =
resppack.bodeplot
new-array(2) = h
new-array =
resppack.bodeplot: 1-by-2
new-array
new-array =
resppack.bodeplot: 1-by-2

Related

Is it possible to average across array of structure sub-fields in Matlab without looping?

I have a function that processes an individual data set, and stores the outcome metrics in a data set like so:
trial_data.output_metric_a.value_1 = 2;
...
trial_1 = trial_data;
This function is applied to a number of different trials and are stored as an array struct:
% trial_1.output_metric_a.value_1 = 4
% trial_2.output_metric_a.value_1 = 2
trials = [trial_1 ; trial_2];
Is it possible to get averages and standard deviations of the sub-field values
without looping through the data structure?
Ideally:
mean_trials = mean(trials)
mean_trials.output_metric_a.value_1 == 3 % true
A possible loop implementation to solve this could be (obviously this leaves much to be desired):
output_metric_a_value_1 = [];
...
for i:length(trials)
output_metric_a_value_1(end+1) = trials(i).output_metric_a.value_1;
... % For each output metric and value
end
mean_trials.output_metric_a.value_1 = mean(output_metric_a_value_1);
You can convert the main struct to cell, then operate on the contents:
% your data base:
trial_1.output_metric_a.value_1 = 4
trial_2.output_metric_a.value_1 = 2
trials = [trial_1 ; trial_2];
% convert to cell:
Ctrials=struct2cell(trials);
Atrials=[Ctrials{:}];
meanTrials=mean([Atrials.value_1])
meanTrials=
3
Special Solution (not-nested struct > array)
As already mentioned, aiming for just one level of struct fields (not nested) one can basically go for a one-liner:
sarr_mean = cellfun(#(fn) mean([sarr.(fn)]), fieldnames(sarr))
Remark: In the not-nested case, there is not really a need to assign the resulting array back to a struct. If required, you can do it analogously to the full solution below.
Full Solution (nested struct > nested struct)
However, with arbitrarily nested arrays, I suggest to use a function such as the following:
% f... function handle
% s... nested struct array
function sarr_res = nestedSarrFun(f, s)
if isstruct(s)
% get fieldnames:
fns = fieldnames(s);
% get content:
con = cellfun(#(fn) nestedSarrFun(f, [s.(fn)]), ...
fns, 'UniformOutput', false);
% create return struct
fnsCon = reshape([fns(:), con(:)]', [1,2*numel(fns)]);
sarr_res = struct(fnsCon{:});
else
sarr_res = f(s);
end
end
Usage Example
Define example struct array and apply mean via nestedSarrFun:
% define example struct array "sarr" with fields
% .foo.bar1
% .bar2
% .dings
sarr = struct();
sarr(1).foo.bar1 = 2;
sarr(1).foo.bar2 = 7;
sarr(1).dings = 1;
sarr(2).foo.bar1 = 5;
sarr(2).foo.bar2 = 5;
sarr(2).dings = 2;
% apply mean to all nested fields:
sarr_mean = nestedSarrFun(#mean, sarr);
Example Result:
sarr_mean.foo.bar1 = 3.5
sarr_mean.foo.bar2 = 6
sarr_mean.dings = 1.5
In Matlab2017 (I am not sure about older versions), an array of structs can return an array of the field of its structs like so:
struct1.x = 1;
struct2.x = 2;
% array of 2 structs:
struct_array = [struct1, struct2];
% array of field x of each struct:
[struct_array.x]
which returns
ans =
1 2
In your case, the data is not in a field of your struct, but in a subfield output_metric_a. Therefore, you first need to this twice:
trial1.output_metric_a.value_1 = 1;
trial2.output_metric_a.value_1 = 2;
trials = [trial1, trial2];
output_metric_a_array = [trials.output_metric_a];
value_1_array = [output_metric_a_array.value_1];
mean_of_value_1 = mean(value_1_array)
which returns
mean_of_value_1 =
1.5000

Pythonic way in matlab to decompose array to variables

So I want to decompose array to multiple variables.
For example,
I have 'data' array of (136,9) size which is of double type.
I want to decompose the values of data(1,:) to multiple variables something like below:
[frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = data(1,:);
In python it was straightforward, but above code gives following error in matlab:
Insufficient number of outputs from right hand side of equal sign to satisfy
assignment.
I can go with something like
frm_id = data(1,1);
seq_id = data(1,2);
%ect
But I do believe there must be matlab (more neat) way to do this operation.
Thanks!
You can use num2cell to convert the matrix to a cell array then copy contents of the cell to each variable:
C = num2cell(data,1);
[frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = C{:};
I can only suggest you to create a function like this:
function [frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = myfunction (data)
frm_id = data(:,1);
seq_id = data(:,2);
xmin = data(:,3);
ymin = data(:,4);
w = data(:,5);
h = data(:,6);
temp1 = data(:,7);
temp2 = data(:,8);
temp3 = data(:,9);
so in your main code
[frm_id,seq_id,xmin,ymin,w,h,temp1,temp2,temp3] = myfunction(data);

Matlab: initialize empty array of matrices

I need to create an empty array of matrices, and after fill it with matrices of the same size.
I have made a little script to explain:
result = [];
for i = 0: 4;
M = i * ones(5,5); % create matrice
result = [result,M]; % this would have to append M to results
end
Here result is a matrix of size 5*25 and I need an array of matrices 5*5*4.
I have been researched but I only found this line: result = [result(1),M];
The issue is that [] implicitly concatenates values horizontally (the second dimension). In your case, you want to concatenate them along the third dimension so you could use cat.
result = cat(3, result, M);
But a better way to do it would be to actually pre-allocate your result array using zeros
result = zeros(5, 5, 4);
And then within your loop fill each "slice" of the 3D array with the values.
for k = 0:4
M = k * ones(5,5);
result(:,:,k+1) = M;
end

Matlab. Storing 2D arrays within 3D arrays

I have defined the following 2D function,
Ngrid = 100;
h = 1/(Ngrid-1);
x = 0:h:1;
y = 0:h:1;
[x y] = meshgrid(x,y);
f = exp(-((1-x).^2)./0.45)
and I want to store this function within the 3D array "c",along the "T" dimension,
k = 0.001;
Tend = 1;
T = 0:k:Tend;
c = zeros(length(T),length(x),length(y));
What I have tried is,
c(1:end,:,:) = f;
but it does not work. ¿Any idea of how can I store the same function within this 3D array?
Thanks in advance.
The subscript dimension mismatch is because you are trying to squeeze 100 * 100 elements into a 1001 x 100 x 100 matrix.
You could do this assignment the following way:
c(1,:,:) = f;
c(2,:,:) = f;
...
c(1001,:,:) = f;
But you can accomplish the same thing using repmat
c = repmat(reshape(f, [1, size(f)]), [numel(T), 1 1]);
Or bsxfun
c = bsxfun(#plus, zeros(numel(T), 1), reshape(f, [1, size(f)]));

Access structure array whose index is stored in a string

I want to get a value from a structure array by code, and I'll have the index stored in a string.
I've tried to run this code:
function M = getdata(matrix,field,varargin)
exp = [];
for i = 1:nargin-3
exp = [exp num2str(varargin{i}) ','];
end
exp = [exp num2str(varargin{nargin-2})];
M = eval('matrix(exp).(Field)');
end
However, it fails.
For example, suppose I have a structure array with 2 fields, A and B. So, I could write
MyStruct(1,1).A
A possible use would be:
M = getdata(MyStruct,A,1,1)
and I want the program to do:
M = MyStruct(1,1).A
How could I do that?
Thanks!
You can use the getfield function:
M = getfield(MyStruct, {1,1} ,'A');
Or if you wanted, say, MyStruct(1,1).A(3).B:
M = getfield(MyStruct, {1,1}, 'A', {3},'B');
For the example you give, this will suffice:
function M = getdata(matrix,field,varargin)
M = matrix(varargin{:}).(field);
which you call like
getdata(myStruct, 'A', 1,1)
which makes that function pretty useless.
But, in general, when you have indices given as strings, you can follow roughly the same approach:
%// Your indices
str = {'1', '2'};
%// convert to numbers
str = cellfun(#str2double, str, 'UniformOutput', false);
%// use them as indices into structure
M = myStruct(str{:}).(field)
And if you really insist, your call to eval is just wrong:
M = eval(['matrix(' exp ').(' field ')']);
And, as a general remark, please refrain from using exp as the name of a variable; it is also the name of a built-in function (the natural exponential function).

Resources