Variable length MATLAB arguments read from variable - matlab

I have a function with variable arguments, declared in the standard way:
[] = foo ( varargin )
and I would like to call it from another function, but specify the arguments programmatically. My best attempt is something like the following:
% bar isn't populated like this, but this is how it ends up
bar = { 'var1' 'var2' 'var3' };
foo( bar );
However, bar is put into a 1x1 cell array, and not interpreted as a 1x3 cell array as I intended. I can't change foo, so is there a workaround?

If you have variables a, b, and c that you want to collect together somewhere and ultimately pass to a function as a series of inputs, you can do the following:
inArgs = {a b c}; % Put values in a cell array
foo(inArgs{:});
The syntax inArgs{:} extracts all the values from the cell array as a comma-separated list. The above is therefore equivalent to this:
foo(a,b,c);
If foo is written to accept a variable-length argument list, then the varargin variable will end up being a 1-by-3 cell array where each element stores a separate input argument. Basically, varargin will look exactly like the variable inArgs. If your call to foo didn't use the {:} operator:
foo(inArgs);
then the varargin variable would be a 1-by-1 cell array where the first element is itself the cell array inArgs. In other words, foo would have only 1 input (a 1-by-3 cell array).

The only way that I'm aware of is to use eval, however I don't have MATLAB here, so I can't check the syntax correctly.
If you coerce the bar into a string of the form "'var1', 'var2', 'var3'", you can do:
eval(["foo(", barString, ")"])
Hope that gets you going and sorry it isn't a comprehensive answer.

Related

MATLAB: Using get in cellfun for a cell array of objects

I've been stuck with this for a while and I couldn't find something similar asked previously (or I have failed in doing so)
My situation is fairly simple: I have a cell array of objects. They are all the same object and I have a get function for this kind of object which is: get (obj, attr), where obj is the object in question and attr is a integer from 1-6. Depending on the number the get function returns the corresponding attribute.
I would like to obtain all of my "position" attributes from all my objects which are in the corresponding cell array (this would be attr = 2). I know that cellfun performs a function on all cells, but the question is, how do I use my get function here for all my objects, taking into account that the function is get (obj, attr) ?
Thanks in advance
Firstly, by using get as a custom function you are shadowing the built-in get function - this is bad practise!
With this in mind, and to avoid confusion with the built-in get function which has similar syntax, I'm going to use getattr as a stand-in for your custom function which accpets an object and an integer 1 to 6.
pos = cellfun( #(obj) getattr( obj, 2 ), myCellOfObjects, 'uni', 0 );
By specifying 'uni', 0, the output doesn't have to be scalar and will be put into a cell array. This is useful when, for example, you have a multi-element array for your position.
This is equivalent to the following loop:
pos = cell( numel(myCellOfObjects), 1 );
for ii = 1:numel(pos)
pos{ii} = getattr( myCellOfObjects{ii}, 2 );
end
If ever in doubt about cellfun or arrayfun, just write a loop first - they are essentially the same but more concise.
There is a trick to this some are unaware of: you can pass multiple arguments to cellfun like this:
cellfun(#(obj,attr) get(obj,attr), {obj1,obj2},{attr1,attr2},'uni',0)
if you want to get one attribute of the cellarray (instead of providing an attribute for every object in the cellarray), then you can simply use this
cellfun(#(x) getattr(x,attr),obj,'uni',0)
put into anonymous function for convenience:
get_attr = #(obj,attr) cellfun(#(x) getattr(x,attr),obj,'uni',0)
%use:
get_attr(obj_in_cellarray,'myattribute')
%returns cell array of object attributes
I haven't run any of these functions since you didn't provide any example data / code. Please test and feedback.

Undefined function 'eq' for input arguments of type 'cell'

I tried to make a function that generates a number of strings.
function [p] = GetPattern (v)
load('code128B.mat')
for a=1:length(code128B)
if v == code128B(a,1)
p=code128B{a,3};
end
end
code128B.mat contains data, first column are numbers while third column are strings. I want to input numbers and produce a string.
why this function produce an error: Undefined function 'eq' for input arguments of type 'cell'.? I don't get it.
Thanks for any help.
For cell arrays, curly braces ({}) are used to extract the contents of the cells, while parentheses (()) are used to extract a subset of the cells (that is, the result is also a cell array).
Use code128B{a,1} instead of code128B(a,1) to get the number instead of a cell containing the number. However, if v is also a cell then you have to use isequal to compare their contents.

Provide variable argument list

I have a function which accepts a variable number of input variables. The problem is, the number of input arguments I'm going to provide varies. As such, I store all the arguments in a structure:
function grandAvg(datafiles)
% Load up all averaged datafiles
avgs = struct();
for n=1:length(datafiles)
avgs(n).avg = load(datafiles{n});
end
My question is, is there a way to expand this argument for the function? I need a way to convert this:
% DOES NOT WORK
avg = ft_timelockgrandaverage(cfg, avgs);
to this:
% WOULD WORK, BUT DO NOT WANT TO TYPE IT OUT
avg = ft_timelockgrandaverage(cfg, avgs(1).avg, ..., avgs(n).avg);
EDIT TO ADD: So apparently my question wasn't clear. I know how to construct the function using varargin. My question was, if I am trying to use a build-in function which I don't want to or can't modify, how can I provide arguments in a variable manner? I.e., I don't know ahead of time how many argument's I'll be providing, so when I call the function, I'll have to call it with X number of arguments. In effect, I'm looking for a way to turn this:
someVar <1xN struct>
into this:
someVar1 <1x1 struct>
someVar2 <1x1 struct>
...
someVarN <1x1 struct>
in a programmatic manner. Thanks!
An alternative to using a structure array to store your data would be to use a cell array. For example:
nFiles = numel(datafiles); %# Number of files
avgs = cell(1,nFiles); %# Initialize an empty cell array
for iFile = 1:nFiles %# Loop over the files
avgs{iFile} = load(datafiles{iFile}); %# Load the data into each cell
end
avg = ft_timelockgrandaverage(cfg, avgs{:}); %# Pass the contents to a function
The syntax avgs{:} dumps the contents of the cell array into what's called a comma-separated list. It is equivalent to typing avgs{1}, avgs{2}, ... , avgs{end}. The syntax foo(:).bar from the answer you found also creates a comma-separated list, but I find that using cell arrays for such a purpose is generally cleaner than using a structure array.
yes you can use variable length input argument list
varargin
http://www.mathworks.com/help/techdoc/ref/varargin.html
So, after playing around, I've got it. Using the example from above:
Given an 1xN struct named foo, where each foo(n) contains the field bar, I would call the function as:
function(foo(:).bar);
This is the same as typing
function(foo(1).bar, foo(2).bar, ..., foo(N).bar);
In this way, I can dynamically expand or shrink foo and still have no problem calling the function.
You can surely do such a thing, by means of the varargin construct in MATLAB. This will be something like:
avg = ft_timelockgrandaverage(cfg, avgs.avg);
And for the function ft_timelockgrandaverage
function output = ft_timelockgrandaverage(config, varargin)
% your code here
varargin will be a cell array: {avgs(1).avg, avgs(2).avg, ..., avgs(3).avg} which you can process.

If a MATLAB function returns a variable number of values, how can I get all of them as a cell array?

I am writing a function to remove some values from a cell array, like so:
function left = remove(cells, item);
left = cells{cellfun(#(i) ~isequal(item, i), cells)};
But when I run this, left has only the first value, as the call to cells{} with a logical array returns all of the matching cells as separate values. How do I group these separate return values into a single cell array?
Also, perhaps there is already a way to remove a given item from a cell array? I could not find it in the documentation.
You have to use () instead of {} to index the cells:
function left = remove(cells, item)
left = cells(cellfun(#(i) ~isequal(item, i), cells));
Using () for indexing will give you a subset of cells, while using {} will return the contents of a subset of cells as a comma-separated list, and only the first entry of that list will get placed in left in your example.
You can check out this MATLAB documentation for more information on using cell arrays.
EDIT: Response to comment...
If you have an operation that ends up giving you a comma-separated list, you can place the individual elements of the list into cells of a cell array by surrounding the operation with curly braces. For your example, you could do:
left = {cells{cellfun(#(i) ~isequal(item, i), cells)}};
The inner set of curly braces creates a comma-separated list of the contents of cells that are not equal to item, and the outer set then collects this list into a cell array. This will, of course, give the same result as just using parentheses for the indexing, which is the more sensible approach in this case.
If you have a function that returns multiple output arguments, and you want to collect these multiple values into a cell array, then it's a bit more complicated. You first have to decide how many output arguments you will get, or you can use the function NARGOUT to get all possible outputs:
nOut = 3; %# Get the first three output arguments
%# Or...
nOut = nargout(#some_fcn); %# Get all the output arguments from some_fcn
Then you can collect the outputs into a 1-by-nOut cell array outArgs by doing the following:
[outArgs{1:nOut}] = some_fcn(...);
It should be noted that NARGOUT will return a negative value if the function has a variable number of output arguments, so you will have to choose the value for nOut yourself in such a case.

Iterating through struct fieldnames in MATLAB

My question is easily summarized as: "Why does the following not work?"
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for i=1:numel(fields)
fields(i)
teststruct.(fields(i))
end
output:
ans = 'a'
??? Argument to dynamic structure reference must evaluate to a valid field name.
Especially since teststruct.('a') does work. And fields(i) prints out ans = 'a'.
I can't get my head around it.
You have to use curly braces ({}) to access fields, since the fieldnames function returns a cell array of strings:
for i = 1:numel(fields)
teststruct.(fields{i})
end
Using parentheses to access data in your cell array will just return another cell array, which is displayed differently from a character array:
>> fields(1) % Get the first cell of the cell array
ans =
'a' % This is how the 1-element cell array is displayed
>> fields{1} % Get the contents of the first cell of the cell array
ans =
a % This is how the single character is displayed
Since fields or fns are cell arrays, you have to index with curly brackets {} in order to access the contents of the cell, i.e. the string.
Note that instead of looping over a number, you can also loop over fields directly, making use of a neat Matlab features that lets you loop through any array. The iteration variable takes on the value of each column of the array.
teststruct = struct('a',3,'b',5,'c',9)
fields = fieldnames(teststruct)
for fn=fields'
fn
%# since fn is a 1-by-1 cell array, you still need to index into it, unfortunately
teststruct.(fn{1})
end
Your fns is a cellstr array. You need to index in to it with {} instead of () to get the single string out as char.
fns{i}
teststruct.(fns{i})
Indexing in to it with () returns a 1-long cellstr array, which isn't the same format as the char array that the ".(name)" dynamic field reference wants. The formatting, especially in the display output, can be confusing. To see the difference, try this.
name_as_char = 'a'
name_as_cellstr = {'a'}
You can use the for each toolbox from http://www.mathworks.com/matlabcentral/fileexchange/48729-for-each.
>> signal
signal =
sin: {{1x1x25 cell} {1x1x25 cell}}
cos: {{1x1x25 cell} {1x1x25 cell}}
>> each(fieldnames(signal))
ans =
CellIterator with properties:
NumberOfIterations: 2.0000e+000
Usage:
for bridge = each(fieldnames(signal))
signal.(bridge) = rand(10);
end
I like it very much. Credit of course go to Jeremy Hughes who developed the toolbox.