Storing handles of objects generated by imline in MATLAB - matlab

I am trying to store a set of object handles in an array. The objects are a series of lines generated by imline(.). I want to store the handles in order to be able to change the property of a desired line (in this case, position).
I know how to do this - however, when I try to fill a matrix with the handles of lines, an error occurs - MATLAB states that conversion from IMLINE to DOUBLE is not possible. This does not happen with other types of objects. Is there a way to circumvent this?
Here is some pseudocode to clarify:
lines=zeros(1,x); % defining empty storage matrix
for idx=1:x
line=imline(ax_handl,[x_1 y_1; x_2 y_2])
set(line,'UserData',idx) % in order to identify independent lines with the number
lines(idx)=line; % here I try to store a line handle as it's made
end
% now in the function responsible for motion of objects, I assign new position to line
line_num=get(gco,'UserData'); % this relates other objects associated with line number
setPosition(lines(line_num),[a b; c d]);

Use the empty static method to create an empty array of the class type:
lines = imline.empty(0,10);
for idx=1:10
line = imline(gca, sortrows(rand(2,2)));
set(line,'UserData',idx)
lines(idx) = line;
end

You may need to fill your matrix with default valued lines in order to create it. The typical approach to preallocating a matrix of objects of size N would be to simply assign an object to the last element in the matrix.
M(N,N)=imline(gca,[NaN NaN],[NaN NaN]); %# set non-displayable vals for x and y
NOTE, the line above will not work with imline as it will call the default constructor for each of the other N*N-1 imline objects in the matrix and a call of imline with no arguments forces user interaction with the current axis.
My advice (if you are pre-allocating) is to define all the default lines explicitly in the matrix:
for k=1:N*N
M(k)=imline(gca,[NaN NaN],[NaN NaN]);
end
%# Reshape (if necessary)
M = reshape(M,[N N]);
Alternatively, you could let Matlab fill the array for you. If you find that you will need this code often, derive a new class from imline. The following example shows the very least that would need to happen. It merely defines a constructor. This example allows you to pass optional arguments to imline as well. If no arguments are specified, the imline object is created with position values as above.
classdef myimline<imline
methods
function obj = myimline(varargin)
if isempty(varargin)
varargin = {gca,[NaN NaN],[NaN NaN]};
end
obj = obj#imline(varargin{:});
end
end
end
Example usage:
%# Generate a 100 element array of `imline` objects,
%# but define the last one explicitly
mat(100)=myimline(gca,[0 1],[0 1]);
The last myimline object in the array has points specified as in the assignment, but the rest of the elements have the default position values [NaN NaN] as above.

Related

Matlab "auto-squeeze" plot

Matlab plot requires the data to be of the same dimension. Meaning, you cannot plot a 1x10 vector with a 1x1x10 vector. This is sometimes necessary. For those purposes, you can use the squeeze function to get rid of the singleton dimensions.
However, this is kind of a hassle. For the plot function specifically, it would be useful to have the argument always squeezed. How would one go about creating a new function, lets call it splot which squeezes every input and passes it onto plot. Here is an attempt (that doesn't work)
function splot(varargin)
for i=1:length(varargin)
varargin{i}=squeeze(varargin{i});
end
plot(varargin)
end
plot(varargin) part fails, because that is simply not how matlab syntax works. But is there any way to achieve what I want? I guess I could write a long if elseif chain where I manually write the case with every possible number of input arguments like:
if length(varargin)==2
plot(varargin{1},varargin{2})
if length(varargin)==3
plot(varargin{1},varargin{2},varargin{3})
But this is going to be very annoying. Any better ideas.
This question is similar to Is there any mechanism to auto squeeze in Matlab / Octave , however, not similar enough, because the other question is for squeezing every vector, which is a bad idea. Here I am asking a way to squeeze only the inputs to the plot function and requiring syntax help.
From the docs there are several ways to call plot. Generally
Just numeric arrays, these can be on their own, or one or more pairs
plot(Y), plot(X,Y) or plot(X1,Y1,...,Xn,Yn)
Numeric arrays as before, with a char array giving the line spec
plot(X,Y,LineSpec) or plot(Y,LineSpec)
Either of the previous two, plus name-value pair options
plot(___,Name,Value)
In any of these cases, you want to squeeze the first N inputs which are numeric, since either of the optional additions have the first non-plottable input as a char.
We can achieve that with the following code, see the comments for details:
function h = splot( varargin )
% Check if there are any optional inputs, which will either be
% LineSpec (which is a char) or name-value pairs (which the
% first of will be a char)
bNumericArg = cellfun( #isnumeric, varargin );
% By default, assume all inputs are arrays to plot
lastArrayArg = numel(varargin);
if ~all(bNumericArg)
% In this case, there are some optional inputs, get last array index
lastArrayArg = find( ~bNumericArg, 1 ) - 1;
end
% Squeeze the arrays
for ii = 1:lastArrayArg
varargin{ii} = squeeze(varargin{ii});
end
% Plot with all inputs, optional output
if nargout > 0
h = plot( varargin{:} );
else
plot( varargin{:} );
end
end
There are two possible cases I've not handled here which the plot function can handle,
Having the first input as the target axes i.e. plot(ax,___), could be achieved by altering the loop slightly to start from 1 or 2 depending if the first input is an axes object
Having pairs of arrays each with their own line spec argument i.e. plot(X1,Y1,LineSpec1,...,Xn,Yn,LineSpecn). The later pairs will be ignored. This would be trickier to handle since you'd likely have to parse all inputs and check whether a char is just a line spec or if you're messing with name-value pairs. Maybe a heuristic to do with "two arrays then a char, repeated". I've never used this syntax so omitting the over-complication for now.

Looping over list of variables in matlab

I have a list of variables (different sized numeric matrices) named Reach1 to Reach7
I want to plot them all as subplots in one figure.
Need a way to loop over each variable as below:
names = {'Reach1' 'Reach2' 'Reach3' 'Reach4' 'Reach5' 'Reach6' 'Reach7'};
for index = 1:7
subplot(3,3,index)
plot(names(index)(:,1),names(index)(:,2));hold on;
plot(names(index)(:,5),names(index)(:,6));
plot(names(index)(:,9),names(index)(:,10));hold off;
end
Is there a better way to do this in matlab?
You cannot access names(index) because it is cell array and those are accessed by names{index}.
If you want to access variable Reach1(1,3) by calling names{1}(1,3), you will fail because Matlab will (try to) return a as an element of char array. This approach can be achieved by eval but do NOT do that! It has many drawbacks and no benefit.
You can simplify your code using Matlabs features, that are not obvious but bloody useful.
Suppose we have all matrices in one cell array Reaches={<Reach1>;<Reach2>;...}:
Reaches={rand(4,12);rand(6,12);rand(8,12);rand(2,12);rand(9,12)}; %declare dummy variables
counter=0;
for Reach=Reaches
counter=counter+1;
subplot(3,3,counter);
plot(Reach(:,[1,5,9]),Reach(:,2,6,10));
end
This code benefits from:
for is able to loop over array elements.
plot is able to process arrays.
(Advanced) Array indexing.
In this example appropriate element names{ii} is passed to Reach variable, counter counter is advanced and plot is supported by matrices containig columns 1, 5 and 9 and 2, 6 and 10 as x and y values, respectively.

Splitting non-continuous sized matrix in vectors

I'm writing an piece of software within Matlab. Here, the user can define a dimension say 3.
This dimension is subsequently the number of iterations of a for loop. Within this loop, I construct a matrix to store the results which are generated during every iteration. So, the data of every iteration is stored in a row of a matrix.
Therefore, the size of the matrix depends on the size of the loop and thus the user input.
Now, I want to separate each row of this matrix (cl_matrix) and create separate vectors for every row automatically. How would one go on about? I am stuck here...
So far I have:
Angle = [1 7 15];
for i = 1:length(Angle)
%% do some calculations here %%
cl_matrix(i,:) = A.data(:,7);
end
I want to automate this based on the length of Angle:
length(Angle)
cl_1 = cl_matrix(1,:);
cl_7 = cl_matrix(2,:);
cl_15= cl_matrix(3,:);
Thanks!
The only way to dynamically generate in the workspace variables variables whos name is built by aggregating string and numeric values (as in your question) is to use the eval function.
Nevertheless, eval is only one character far from "evil", seductive as it is and dangerous as it is as well.
A possible compromise between directly working with the cl_matrix and generating the set of array cl_1, cl_7 and cl_15 could be creating a structure whos fields are dynamically generated.
You can actually generate a struct whos field are cl_1, cl_7 and cl_15 this way:
cl_struct.(['cl_' num2str(Angle(i))])=cl_matrix(i,:)
(you might notice the field name, e. g. cl_1, is generated in the same way you could generate it by using eval).
Using this approach offers a remarkable advantage with respect to the generation of the arrays by using eval: you can access to the field od the struct (that is to their content) even not knowing their names.
In the following you can find a modified version of your script in which this approach has been implemented.
The script generate two structs:
the first one, cl_struct_same_length is used to store the rows of the cl_matrix
thesecond one, cl_struct_different_length is used to store arrays of different length
In the script there are examples on how to access to the fileds (that is the arrays) to perform some calculations (in the example, to evaluate the mean of each of then).
You can access to the struct fields by using the functions:
getfield to get the values stored in it
fieldnames to get the names (dynamically generated) of the field
Updated script
Angle = [1 7 15];
for i = 1:length(Angle)
% do some calculations here %%
% % % cl_matrix(i,:) = A.data(:,7);
% Populate cl_matrix
cl_matrix(i,:) = randi(10,1,10)*Angle(i);
% Create a struct with dinamic filed names
cl_struct_same_length.(['cl_' num2str(Angle(i))])=cl_matrix(i,:)
cl_struct_different_length.(['cl_' num2str(Angle(i))])=randi(10,1,Angle(i))
end
% Use "fieldnames" to get the names of the dinamically generated struct's field
cl_fields=fieldnames(cl_struct_same_length)
% Loop through the struct's fileds to perform some calculation on the
% stored values
for i=1:length(cl_fields)
cl_means(i)=mean(cl_struct_same_length.(cl_fields{i}))
end
% Assign the value stored in a struct's field to a variable
row_2_of_cl_matrix=getfield(cl_struct_different_length,(['cl_' num2str(Angle(2))]))
Hope this helps.

MATLAB cell array of function handles - How does it work?

I am trying to understand the following commands of a MATLAB script :
global operatorObj
calcEVR_handles = operatorObj.calcEVR_handles;
m = operatorObj.nInputs
E = zeros(m,1);
V = zeros(m,1);
R = zeros(m,m);
for i=1:m
[E(i), V(i), R(i,i)] = calcEVR_handles{i}(t,x);
end
What can calcEVR_handles be, if t is a float and x is a vector?
calcEVR_handles (to me) looks like a cell array where each element is a handle to a function. Each element in calcEVR_handles is an anonymous function that takes in a single value t and a single vector x. As such, by doing calcEVR_handles{i}, you would access the corresponding function stored at the ith element in the cell array. Once you have access, you then pass your parameters to this function and it gives you those three outputs.
To show you an example of this working, consider the following cell array that works similarly to calcEVR_handles.
calcCellFunc = {#sin, #cos, #tan};
This is a three element cell array, where each element is a handle to a function. The # is a special character in MATLAB that denotes that you are creating a handle to a function. It's also used to create anonymous functions, but let's shelve that for this answer. You can read more about it here if you want to delve into more detail regarding this.
Back to our cell array of handles, we will make handles for sin, cos and tan. You can then iterate over your cell array by accessing the function you want by calcCellFunc{idx} where idx is the element you want in the cell array. This will ultimately give you the function stored at index idx. Once you do that, you can then call the function and specify whatever inputs you want (or none if it doesn't take any inputs). Here's a quick example for you. Let's create a random 5 x 5 matrix, and run through each function with this matrix serving as the input. We then take each of these outputs and store them into a corresponding slot in an output cell array. As such:
rng(123); %// Set seed for reproducibility
M = rand(5);
calcCellFunc = {#sin, #cos, #tan};
out = cell(1, numel(calcCellFunc)); %// To store the results for each function
for idx = 1 : numel(calcCellFunc)
out{idx} = calcCellFunc{idx}(M); %// Get the function, then pass
%// the matrix M to it
end
If you want to make things clear, you could split up the out statement to this instead:
func = calcCellFunc{idx}; %// Get access to the function
out{idx} = func(M); %// Pass M to this function
If you're new to handles / anonymous functions, you should probably use the above code first to make it explicitly clear on what MATLAB is doing. You are first getting access to the function you want that is stored in the cell array, and then you pass your arguments to this function.
If we display the output, we get:
>> celldisp(out)
out{1} =
0.6415 0.4106 0.3365 0.6728 0.5927
0.2823 0.8309 0.6662 0.1815 0.7509
0.2249 0.6325 0.4246 0.1746 0.6627
0.5238 0.4626 0.0596 0.5069 0.5737
0.6590 0.3821 0.3876 0.5071 0.6612
out{2} =
0.7671 0.9118 0.9417 0.7398 0.8054
0.9593 0.5564 0.7458 0.9834 0.6604
0.9744 0.7745 0.9054 0.9846 0.7489
0.8518 0.8866 0.9982 0.8620 0.8191
0.7522 0.9241 0.9218 0.8619 0.7502
out{3} =
0.8363 0.4503 0.3573 0.9094 0.7359
0.2942 1.4934 0.8932 0.1845 1.1370
0.2308 0.8167 0.4690 0.1773 0.8850
0.6149 0.5218 0.0597 0.5880 0.7004
0.8761 0.4135 0.4205 0.5884 0.8814
The first element of the output cell array has the output when you pass M to sin, the second when you pass M to cos, and the third when you pass M to tan.
So the next question you're asking... why is this useful?
Point #1 - Nix the copying and pasting
This kind of code writing is very useful because if you want to use the same inputs and supply them to many different functions, we would naturally be inclined to do some copying and pasting. Take each of your function names, and create a single line for each. Each line would call the corresponding function you want, followed by the input arguments. This can become quite tedious, and so one smart way to do it would be to place your function name as a handle into a cell array, and to write one for loop that goes over all of the functions dynamically. You could even explore cellfun and escape using the for loop to iterate over all of the function handles too, but I'll leave that for you to read up on.
In this way, you have very maintainable code and if you want to remove functions that don't need to be run, just remove the handles from the cell array rather than scrolling down to where the line that invokes this function is located and removing that.
This is actually a very common technique in computer science / software engineering in general. In fact, this is actually quite close to what are known as function pointers. This is MATLAB's cheap way of doing it, but the logic behind this is essentially the same.
Point #2 - Higher Order Functions
Another way this is useful is if you have a function where one (or more than one!) of the inputs is a function, and you also specify inputs into this function as additional parameters to this function. This is what is known as a higher order function. The outputs would be based on using this input function, and the additional inputs you specify to it and the outputs are based on using this input function and the inputs you specify for this function.
One very good example is the fzero function in MATLAB. The goal is to find the root of a non-linear function, and the first parameter is a handle to a function that you specify. The base behaviour behind how fzero works is the same no matter what the function is. All you have to do is specify the function you want to solve and the initial guess of where you think this root is.
All in all, anonymous functions are very useful.

Matlab: Can I refer to array indices via unique names?

Suppose I have a column matrix pols containing vectors of [theta, rho, z].
Which means, if I have 9 such vectors, it will be a 9x3 matrix.
It is quite handy to have them arranged as such, because I can just feed any one of them to functions like pol2cart:
cart3 = pol2cart(pols(3,:));
and for a certain vector, I can find its components via the indices 1, 2, 3:
rho5 = pols(5,2);
But sometimes the matrix is actually within another wider matrix, and could be in the middle instead of the beginning, such that the above might become:
rho5 = pols(5,6);
In order to make the code more readable in case someone else has to maintain it, is there anyway to refer to an index via a unique name? Like
rho5 = pols(5).rho;
where it could be defined earlier that .rho maps to the column which has the value of rho.
I've ventured into converting matrices to cells then to array using mat2cell and cell2struct but it doesn't seem practical. Or, I could make an array of structs, but then I lose the ability to do pol2cart(pols), and instead must do
pol2cart(pols.theta, pols.rho, pols.z);
So to repeat the question: can I map the indices to unique names?
For the default MATLAB data types, no, you can't really do that. You could, however, create your own new data type (i.e. class object) to store your data. Within the class definition you would overload the subsref method to define how subscripted referencing (i.e. using (), {}, or .) behaves for your new object. This could get rather tricky with regards to dealing with arrays of objects, but it is possible.
Note that you would also have to create overloaded methods for all the existing functions you want to use on your new data type. Specifically, you would have to create a pol2cart method for your object that could internally call the built-in pol2cart function with the appropriate pieces of data from your object passed as arguments.
...And this brings me to a simpler solution for your current situation. Instead of making a whole new type of class object, you could create a structure array (or scalar structure of arrays) to store your data and simply create a new overloaded pol2cart function specifically for struct data types that will simplify the calling syntax.
I discuss more details of overloading functions for built-in data types in two other answers here and here. In short, you would create a folder called #struct and place it in a folder on your MATLAB path. In this #struct folder you would then put this overloaded function:
function varargout = pol2cart(polarCoordinates)
[varargout{1:nargout}] = pol2cart(polarCoordinates.theta, ...
polarCoordinates.rho, ...
polarCoordinates.z);
end
Note that this is a stream-lined version of the function, without error checks on the input, etc. Now, let's make some sample data:
pols = rand(9, 3); %# A 2-D array of data
polStruct = struct('theta', pols(:, 1), ... %# Convert it to a scalar
'rho', pols(:, 2), ... %# structure of arrays
'z', pols(:, 3));
And you could access the rho value of the fifth row as follows:
rho5 = pols(5,2);
rho5 = polStruct.rho(5);
If you wanted to convert from polar to cartesian coordinates, here's how you would do it for each data type:
[X,Y,Z] = pol2cart(pols(:,1), pols(:,2), pols(:,3)); %# Calls the built-in one
[X2,Y2,Z2] = pol2cart(polStruct); %# Calls the overloaded one
And you can check that they each give identical results as follows:
>> isequal([X Y Z],[X2 Y2 Z2])
ans =
1 %# True!
OK, the formal answer is probably "no" as given by woodchips above. However, if you really want to do something like that, you might be able to use a semi-hack. Specifically, you can define a class and overload an operator to achieve (almost) what you want. Unfortunately, I see that Matlab doesn't allow overloading ., so you have to use some other operator. (see edit below)
Just to give you the idea, here is a class that returns the i-th row of a matrix M by M^i.
classdef Test
properties
M;
end
methods
function this = Test(M)
this.M = M;
end
function res = mpower(this, i)
res = this.M(i, :);
end
end
end
And it can be run like this:
>> tmp = Test([1 2; 3 4]);
>> tmp^1
ans =
1 2
>> tmp^2
ans =
3 4
Use at your own risk! :)
Edit:
I was wrong above. As mentioned in gnovice's answer you can actually define the . operator for a custom class using method subsref.
No. You cannot do so. As simple as that.