Iterating over Matlab struct - matlab

I have a 1x1 Matlab struct with 15 fields
results =
RAR_no_compartments_2_0: [1x1 struct]
RAR_no_compartments_2_1: [1x1 struct]
RAR_no_compartments_2_10: [1x1 struct]
RAR_no_compartments_2_11: [1x1 struct]
RAR_no_compartments_2_12: [1x1 struct]
RAR_no_compartments_2_13: [1x1 struct]
RAR_no_compartments_2_14: [1x1 struct]
RAR_no_compartments_2_2: [1x1 struct]
RAR_no_compartments_2_3: [1x1 struct]
RAR_no_compartments_2_4: [1x1 struct]
RAR_no_compartments_2_5: [1x1 struct]
RAR_no_compartments_2_6: [1x1 struct]
RAR_no_compartments_2_7: [1x1 struct]
RAR_no_compartments_2_8: [1x1 struct]
RAR_no_compartments_2_9: [1x1 struct]
I'm trying to cycle through each of these in a for loop:
model_names=fieldnames(results); %get the names of each sub-struct
fieldname_dims=size(fieldnames(results)); %get dimensions of each struct
for i=1:fieldname_dims(1), %iterate over number of substructs
name=model_names(i) %get the model name
results.(name) %access the substruct
end
However Matlab returns the following error:
Argument to dynamic structure reference must evaluate to a valid field name.
Could somebody please explain to me why this is an invalid field name?

This is precisely what structfun is made for. It allows you to loop through all the fields of a structure.
a = struct('a', 1, 'b', 2, 'c', 3);
structfun(#(x)disp(x), a)
1
2
3
Alternately, you may consider storing an array of structures rather than a structure where the fields have numbers in them like you have. Any time that you are reliant on a fieldname to know ordering, it may be better to use a different data structure.
For in your data, rather than having a fieldname of RAR_no_compartments_2_0 you'd simply assign the struct assigned to that field by index
RAR_no_compartments(1) = results.RAR_no_compartments_2_0;
RAR_no_compartments(2) = results.RAR_no_compartments_2_1;
...
This way, rather than a 1 x 1 struct with 15 fields, you'd have a 1 x 15 array of structs which is much easier to deal with natively within MATLAB.
Just a thought.

The problem is that fieldnames returns a cell array, so you have to use curly brackets to access the content of a cell. This should work:
model_names=fieldnames(results);
fieldname_dims=size(fieldnames(results),1);
for i=1:fieldname_dims
name=model_names{i};
results.(name)
end
The whole thing can be simplified by actually iterating over the cell array instead of using a counter and temporary variables:
for name = fieldnames(results).'
results.(name{:}) % do whatever with your field
end
However, the correct way to access all fields of a struct is structfun—see Suever's answer.

Related

Undefined operator '*' for input arguments of type 'struct'

MATLAB :
vso' is graph based visual saliency map (gbvs) of original image, and 'vsd' is graph based visual saliency map (gbvs) of blurred version of the same image.
vso=gbvs('../images/I03.bmp');
vsd=gbvs('../images/i03_17_5.bmp');
Trying to find out similarity map between these both image as -
Svs=(2*vso*vsd+cvs)/(vso^2+vsd^2+cvs);
where cvs is constant, cvs =1.27
Error is : Undefined operator '*' for input arguments of type 'struct'
vso=gbvs('../images/I03.bmp')
vso =
master_map: [24x32 double]
master_map_resized: [384x512 double]
top_level_feat_maps: {[24x32 double] [24x32 double] [24x32 double]}
map_types: {'dklcolor' 'intensity' 'orientation'}
intermed_maps: [1x1 struct]
rawfeatmaps: [1x1 struct]
paramsUsed: [1x1 struct]
vsd=gbvs('../images/i03_17_5.bmp')
vsd =
master_map: [24x32 double]
master_map_resized: [384x512 double]
top_level_feat_maps: {[24x32 double] [24x32 double] [24x32 double]}
map_types: {'dklcolor' 'intensity' 'orientation'}
intermed_maps: [1x1 struct]
rawfeatmaps: [1x1 struct]
paramsUsed: [1x1 struct]
These are variable struct type...

Using Cell Array Contents to Create Struct Entries

Say that I have two cell arrays, A and B, that contain string values. I wish to populate a struct S such I generate every possible combination of S.valueinA.valueinB = 1. I am currently trying to accomplish this with two nested for-loops that iterate through every possible combination and wanted to ask if there is a more efficient way to solve this problem in MATLAB.
If you want to make dynamic field names in structures, I don't see how else you can do it without two for loops. Let's say we have two cell arrays A and B that consist of string entries.
For my example, apologies for the strings inside these arrays in advance as I couldn't think of anything better at the moment!
Is this what you're trying to achieve?
S = struct();
A = {'hello', 'my', 'name', 'is', 'ray'};
B = {'i', 'am', 'doing', 'awesome'};
for idx = 1 : numel(A)
for idx2 = 1 : numel(B)
S.(A{idx}).(B{idx2}) = 1;
end
end
This creates a nested structure S such that for each element in A, this becomes a field in S where this field is another structure that contains fields with names coming from all elements in B.
If we displayed S, we get:
>> S
S =
hello: [1x1 struct]
my: [1x1 struct]
name: [1x1 struct]
is: [1x1 struct]
ray: [1x1 struct]
If we accessed the hello field of S, we get:
>> S.hello
ans =
i: 1
am: 1
doing: 1
awesome: 1
Similarly, if we accessed the my field, we get:
>> S.my
ans =
i: 1
am: 1
doing: 1
awesome: 1
Therefore, if we want to get the hello field followed by the am field, we do:
>> S.hello.am
ans =
1

Control Masks Programmatically for Simulink block

I have a problem with simulink block properties. I need to check if block has parameter with name "paramName". If this parameter is absent I need to add it.
For this I want to get mask parameters:
p = Simulink.Mask.get(blockName);
This example I get from help. But Simulink show following error:
undefined variable "Simulink" or class "Simulink.Mask.get"
What should I do for solving my problem?
You probably need to use get_param in combination with the DialogParameters property, e.g.:
block_params = get_param(%block_path%,`DialogParameters`);
The output block_params is a structure with all the parameters of that particular block. Replace %block_path% by the path to the block in question or use gcb for the current block. There is an example on the documentation page for get_param:
Get a Block Parameter Value and Attributes
List the block parameter
names for the Inertia block in the Requisite Friction subsystem of the
sldemo_clutch model.
block_params = get_param('sldemo_clutch/Friction Mode Logic/Requisite Friction/Inertia Ratio',... 'DialogParameters')
ans =
Gain: [1x1 struct]
Multiplication: [1x1 struct]
ParamMin: [1x1 struct]
ParamMax: [1x1 struct]
ParamDataTypeStr: [1x1 struct]
OutMin: [1x1 struct]
OutMax: [1x1 struct]
OutDataTypeStr: [1x1 struct]
LockScale: [1x1 struct]
RndMeth: [1x1 struct]
SaturateOnIntegerOverflow: [1x1 struct]
SampleTime: [1x1 struct]

Removing Structures

I am programming a GUI and I have a variable structure like:
bin: 0.2000
Logical1: 0
Logical2: 0
Matrixraw: {[1x1 struct] [1x1 struct]}
Matrixfiltered: {[1x1 struct] [1x1 struct]}
Matrixcorrected: {[1x1 struct] [1x1 struct]}
Every input file has its own matrix. In this case, we have two input files because every Matrix has two sructures. If we put 3 input files would be 3 structures and so on.
I want to make a button that given one index 1,2,3.. erases the i'th component from the Matrix structure. So, if you type 2 it will erase the second component of the matrix and would give:
bin: 0.2000
Logical1: 0
Logical2: 0
Matrixraw: {[1x1 struct]}
Matrixfiltered: {[1x1 struct]}
Matrixcorrected: {[1x1 struct]}
Thanks.
If you want to delete a member of structure:
Matrixraw = struct('field1', 1, 'field2', '2')
Matrixraw =
field1: 1
field2: 2
// delete first element of structure
Matrixraw(1) = []
Matrixraw =
field1: []
field2: []
The syntax below will empty the structure and remove completely your variable data:
// both works
Matrixraw = {}
Matrixraw = []
Here is a simple way to do it.
Suppose you have this:
Matrixfiltered= {[1 2], {}, 4}
and now we want to remove the second one:
Matrixfiltered(2) = []
Now you have this:
Matrixfiltered= {[1 2], 4}
Just give it a try!

Find Values in cell array of struct

I have two cell array's with structure in it.
example:
xmlFB =
Columns 1 through 5
[1x1 struct] [1x1 struct] [1x1 struct] [1x1 struct] [1x1 struct]
xmllink =
Columns 1 through 3
[1x1 struct] [1x1 struct] [1x1 struct]
xmlFB{1}
ans =
Param: {[1x1 struct] [1x1 struct]}
InterChartConnection: [1x1 struct]
Tasks: [1x1 struct]
Attributes: [1x1 struct]
xmllink{1}
ans =
Attributes: [1x1 struct]
In "xmllink" there is the struct "Attributes" and in there is the Field "Name" with the Value "EN1"
And in xmlFB in the struct "Attributes" there are two Fields "Name" and "Typ"
The Names are unique.
What i want to do is to find the "Typ" in "xmlFB" from the names in the "xmllink".
First i wanted to do with a Loop, but the i read about these arrayfun/structfun/cellfun functions from Matlab.
Is there a way to do this with these? Or is a Loop better?
Let's assume that all variables in Names and Typ are strings. (Should work for scalars as well.)
Here is how to get the values into cell arrays and link them.
% create cell arrays
xmllinkname = cellfun(#(x) x.Attributes.Name, xmllink, 'UniformOutput',0);
xmlFBname = cellfun(#(x) x.Attributes.Name, xmlFB, 'UniformOutput',0);
xmlFBtyp = cellfun(#(x) x.Attributes.Typ, xmlFB, 'UniformOutput',0);
% match names
[idx1, idx2] = ismember(xmllinkname,xmlFBname);
idx2(idx2==0)=[]; % in case some names in xmllink absent in xmlFB
% get matched names and typ
xmllinknamematched = xmllinkname(idx1);
xmllinktyp = xmlFBtyp(idx2);
Since the order of values in the first cell arrays will be the same as in your original cell arrays of structures, you can use those indices idx1 and idx2 to match the structures as well.
xmllinkmatched = xmllink(idx1);
xmlFBmatched = xmlFB(idx2);
Of course, you can avoid creating the temporary arrays and put the first two cellfun statement into ismember statement.
Use the loop.
First things first: only start worrying about performance when it is actually a problem, and only after you get it right.
Now, if I understood you correctly, here are generally two ways to accomplish what you want:
% create some bogus data with the same structure
% ---------------------------
f_xmllink = #(N) struct(...
'Attributes', struct(...
'Name', num2str(N))...
);
f_xmlFB = #(N) struct(...
'Attributes', struct(...
'Name', num2str(N),...
'Typ' , num2str(N))...
);
% using numbers as names
xmllink = {
f_xmllink(190)
f_xmllink(331) % 2
f_xmllink(321) % 3
f_xmllink(239)
};
xmlFB = {
f_xmlFB(331) % 1
f_xmlFB(200)
f_xmlFB(108)
f_xmlFB(321) % 4
f_xmlFB(035)
};
% Example of a no-loop approach
% ---------------------------
tic
s_exp = #(s, field) [s.(field)];
s_exp_C = #(s, field) {s.(field)};
one = s_exp_C(s_exp( [xmllink{:}], 'Attributes'), 'Name');
two = s_exp_C(s_exp( [xmlFB{:}], 'Attributes'), 'Name');
[i,j] = find(strcmp(repmat(one,numel(two),1), repmat(two,numel(one),1).'));
s_exp_C(s_exp([xmlFB{i}], 'Attributes'), 'Typ')
toc
% Example of a loop approach
% ---------------------------
tic
for ii = 1:numel(xmllink)
S = [xmlFB{:}];
S = [S.Attributes];
S = {S.Name};
ind = strmatch(xmllink{ii}.Attributes.Name, S);
if ~isempty(ind)
xmlFB{ind}.Attributes.Typ
end
end
toc
Output:
% no-loop
ans =
'331' '321' % correct findings
Elapsed time is 0.001103 seconds.
% loop
ans =
331 % correct findings
ans =
321
Elapsed time is 0.000666 seconds. % FASTER!
Granted, it's not a fair test to compare the performance, but I think everyone will agree that the looped version will at the very least not be slower than the non-loop version.
More importantly, speed isn't everything -- how long did it take you to understand the no-loop solution? Chances are you understood the loop solution in one read, whereas the no-loop solution is a lot more complicated and will have to be thoroughly documented and tested etc. Also, changes to the no-loop solution will be harder to implement than changes in the loop solution.
That advice to not use loops in Matlab is completely outdated; please ignore it :)