Matlab Array with Same name Name - matlab

I am writing some Matlab code that I am parsing into c++. The C++ Looks like this:
ICOMPL[dataPath].Value =5;
How to write this in Matlab so that the syntax is similar? For example;
ICOMPL = [0,1,2,3];
Let's me do
ICOMPL(datapath+1) = 5;
But how to add the value part? I would need that each element in the array would have the name value.

Note that MATLAB is not C++ so not everything has to be the same, specially when you get to objects. My answer assumes that ICOMPL is not an object from a class, but an struct:
You can make structs in MATLAB, also arrays of structs.
A struct is as easy as
ICOMPL.Value= 5;
An array of structs:
ICOMPL(datapath+1).Value = 5;
So each of ICOMPL will be a whole struct. Note that you may not need this, and you may want to have
ICOMPL.Value= 1:5;
A single struct with several values on each of its elements. Often this last one is easier to work with in MATLAB. That's your decision to make.

Related

Define Multiple Enums in a Single File in Matlab

Is it possible to define multiple enumerations in a single Matlab file? Or is it possible to have "local" enums in the same way we can define local funtions at the end of a file?
I am working on a project where it would be handy to have multiple enumeration classes, but it is annoying to use a classdef every time because it requires a separate file, and this means that there are lots of short files whose sole purpose it is to define enumerations. At the moment, each enumeration looks like this:
classdef exampleEnumType < uint32
enumeration
zero(0),
one(1),
two(2),
end
end
Is there a way to compactly define enumerations in Matlab so that I do not need a separate file for each (using Matlab 2021a)?
First of all, having lots of short files is the normal situation in MATLAB. Working around that is possible but oftentimes futile.
Traditionally in MATLAB, constant values are defined as a function. For example, pi is a function. It looks something like this:
function v = pi
v = 3.14159
By making the constant into a function, it is available from everywhere without first running code to define those constants.
An enumeration is nothing more than a series of constants. The same can be accomplished with a struct:
exampleEnumType = struct('zero',0, 'one',1, 'two',2);
Since fairly recently (R2019b), MATLAB allows dot indexing into the output of a function call, but you do need to use empty parenthesis in the function call. Thus, we can declare the above struct the same way we did with constants:
function v = exampleEnumType
v = struct('zero',0, 'one',1, 'two',2);
This allows to do exampleEnumType().zero (almost) like with the enum or with a struct variable.
So how do we extend this to defining multiple of these in a single file? If a common prefix is no problem, we can define a class with static member functions, each one declaring a constant:
classdef constants
methods(Static)
function v = pi
v = 3.14159
end
function v = exampleEnumType
v = struct('zero',0, 'one',1, 'two',2);
end
end
end
We now have constants.pi and constants.exampleEnumType().zero.
Alternatively, create a single function that returns a more complex struct as follows:
function v = constants
v.pi = 3.14159;
v.exampleEnumType = struct('zero',0, 'one',1, 'two',2);
This allows us to do constants().exampleEnumType.zero.
Note that the above will not work in the same way for MATLAB releases prior to R2019b. For older versions of MATLAB, the last method (a function constants) would be the best approach. The user would just need to do constants = constants; at the top of any function needing to use the constants. This shadows the function with a variable of the same name, so that constants.exampleEnumType.zero works as expected.
You can use a map...
exampleEnum = containers.Map( {'zero','one','two'}, {0,1,2} );
usage looks like
exampleEnum('zero') % = 0
I'm thinking you might want to use categorical arrays here, and stick "enumerations" of their valid values as constants in a common class.
classdef Constants
properties (Constant)
Foods = categorical(["apple", "banana", "pear"])
SupportedProtocols = categorical("http", "https", "ftp")
SpeedOfGravityMps = 9.86
end
end
If you want them to be true Matlab enumerations, then yeah, you're stuck with a separate file for each.

Assigning values to fields in a 2D array in MATLAB

I have a relatively simple problem that my Google-fu hasn't managed to solve that I think must have a solution.
I have a m-by-n array of values, and I am trying to assign them to fields in a m-by-n structure. This is trivial using a for loop (shown below), I am just wondering there a better/more efficient way of doing it.
values = rand(4,8);
for i = 1:4
for j = 1:8
val_struct(i,j).a = values(i,j);
end
end
Since I need to do this for a lot of fields, I am a bit reluctant to just run through a bunch of for loops if I don't absolutely need to.
You can use num2cell and struct :
val_struct = struct('a', num2cell(values));
Note that numeric arrays are much more efficient than struct arrays.

error in array of struct matlab

I want to train data on various labels using svm and want svm model as array of struct. I am doing like this but getting the error:
Subscripted assignment between dissimilar structures.
Please help me out
model = repmat(struct(),size);
for i=1:size
model(i) = svmtrain(train_data,labels(:,i),'Options', options);
end
A structure array in MATLAB can only contain structures with identical fields. By first creating an array of empty structures1 and then trying to fill it with SVMStruct structures, you try to create a mixed array with some empty structures, and some SVMStruct structures. This is not possible, thus MATLAB complains about "dissimilar structures" (not-equal structures: empty vs. SVMStruct).
To allocate an array of structs, you will have to specify all fields during initialization and fill them all with initial values - which is rather inconvenient in this case. A very simple alternative is to drop this initialization, and run your loop the other way around2,3:
for ii=sizeOfLabels:-1:1
model(ii) = svmtrain(train_data,labels(:,ii),'Options', options);
end
That way, for ii=sizeOfLabels, e.g. ii=100, MATLAB will call model(100)=..., while model doesn't exist yet. It will then allocate all space needed for 100 SVMStructs and fill the first 99 instances with empty values. That way you pre-allocate the memory, without having to worry about initializing the values.
1Note: if e.g. size=5, calling repmat(struct(),size) will create a 5-by-5 matrix of empty structs. To create a 1-by-5 array of structs, call repmat(struct(),1,size).
2Don't use size as a variable name, as this is a function. If you do that, you can't use the size function anymore.
3i and j denote the imaginary unit in MATLAB. Using them as a variable slows the code down and is error-prone. Use e.g. k or ii for loops instead.

Matlab: Matrix of ClassificationKNN class objects

For classification I'm building a number of models for a classifier in MATLAB. I use the class ClassificationKNN for this.
I would very much like to store multiple models (or objects of this class) inside a matrix.
Normally you could access and create matrices inside a matrix with the curly braces ({}).
My loop looks like this:
models = []
for i = 1:length(x)
models = [models, {ClassificationKNN.fit(x,y)}]
end
Unfortunately this returns a matrix models of size (1,3) but all cells are empty which means the models are lost...
How can I make sure every model is stored in a matrix? I need to do this because I need all models later in my calculations and the position in the matrix is important...
Any ideas?
You want a cell array of models, right? It sure looks that way, if that will work try this:
models = {}
for ii = 1:length(x)
models = [models, {ClassificationKNN.fit(x,y)}]
end
Also, you loop through calling ClassificationKNN.fit(x,y) with the same arguments every time, is this just a test, or pseudo-code for an example. Like the comment says, it's best to preallocate like:
models = cell(length(x),1);
for ii = 1:length(x)
models{ii} = ClassificationKNN.fit(x,y);
end
But, either way is likely fine.
Thanks to macduffs post I finally figured out what was going on. Whilest reading his proposition I realised that that indeed should be the correct way if getting a cell array of objects.
After trying it, the array again seemed empty when opening it in the variable editor. I tried calling the first cell in the array to see if it was indeed empty and it was not. It returned the object I had stored in it. This means the question was answered.
I then reverted back to my own method to see if that worked as well and it did. When calling a cell it also returned an object.
Bottom line:
Do not trust the variable editor ^^.

Struct management

I am writing a solution that manages data from an eye tracker. I currently hold the data in a N x 5 matrix, with the following columns:
X Position, Y Position, timestamp, Velocity, Acceleration
Each row represents a single sample from the eye tracker (which runs at 1000Hz).
At present, I access the data in the form of a matrix - e.g. if I want to access the velocity for sample #600, I use 'dataStream(600,4)'.
This is fine, but I'd prefer my code to be more readable. The '4' could be confusing; something like dataStream.velocity(600) would be ideal. I understand that this would be a simple use of STRUCT. However, there are situations in which I need to copy an entire sample (i.e. all columns from one row of my matrix). As I understand it, this would not easily be achieved in a STRUCT object, as the various arrays in each STRUCT sub-heading are not intrinsically linked. I would have to (I think) copy each element separately, for example if I wanted to copy sample #100, I believe I would need to copy dataStream.xPos(100), dataStream.yPos(100), dataStream.timestamp(100) and so on separately.
Is there something I'm missing with regards to management of STRUCTs, or would I be better off saving the hassle and sticking with the matrix approach?
If it is just for an increased readability, I would not use structs, but rather use an quite simple approach by defining variables for the different columns of your data matrix. See for instance:
xPosition = 1;
yPosition = 2;
timestamp = 3;
Velocity = 4;
Acceleration = 5;
With this variables you can write quite meaningful queries, for instance, instead of dataStream(600,1) you would write:
dataStream(600, xPosition)
Note that you also could define more complex queries, for instance
position = [1 2];
wholeSample = 1:5;
to query the multiple columns at once.
You can copy struct easily
s = struct(another_struct);
In terms of performance, struct will be slower than matrix. Use readable constant to replace your numerical indices as suggested by #H.Muster.