Understanding the syntax - matlab

I have this couple of lines which is difficult to understand..
oframes1 = do_localmax( difofg.octave{o}, 0.8*thresh, difofg.smin ) ;
oframes = [oframes1 , do_localmax( - difofg.octave{o}, 0.8*thresh, difofg.smin)] ;
here,
do_localmax is a function
thresh is a variable
difofg is also a function
I understand that the 1st line calls the function and passes the parameters but it is difficult understanding the second line and also what kind of syntax is difofg.octave{o}

Syntactically:
difofg is not a function; it's a variable, probably a struct or a class object. difofg.octave and difofg.smin get the element named octave or smin from that struct/object.
difofg.octave is apparently a cell array, and difofg.octave{o} gets the oth element of that cell array.
The second line creates an array with two elements: the first is oframes1, and the second is the result of the second call to do_localmax. Maybe this equivalent code will make it clearer what's happening:
oframes1 = do_localmax( difofg.octave{o}, 0.8*thresh, difofg.smin);
oframes2 = do_localmax( -difofg.octave{o}, 0.8*thresh, difofg.smin);
oframes = [oframes1, oframes2];

Related

vectorize a function with multiple variables

Consider the arbitrary function:
function myFunc_ = myFunc(firstInput, secondInput)
myFunc_ = firstInput * secondInput;
end
Now imagine I want to map the above function to an array for the first input firstInput, while the second input secondInput is constant. For example, something like:
firstVariable = linspace(0., 1.);
plot(firstVariable, map(myFunc, [firstVariable , 0.1]))
where 0.1 is an arbitrary scalar value for the secondInput and firstVariable array is an arbitrary array for the firstInput.
I have looked into the arrayfun() function. However, I don't know how to include the constant variable. Plus it seems like the syntax between MATLAB and Octave are different, or maybe I'm mistaken. It is important for me to have a cross-compatible code that I can share with colleagues.
Assuming in the original function you were multiplying two scalars and you want to vectorise, then
function myFunc_ = myFunc(firstInput, secondInput)
myFunc_ = firstInput .* secondInput;
end
should work just fine.
Then plot it directly:
plot( firstVariable, myFunc(firstVariable , 0.1) )
I'm afraid the arbitrary examples given in the original question were too simplified and as a result, they do not represent the actual issue I'm facing with my code. But I did manage to find the right syntax that works inside Octave:
plot(firstVariable, arrayfun(#(tempVariable) myFunc(tempVariable, 0.1), firstVariable))
basically the
#(tempVariable) myFunc(tempVariable, 0.1)
creates what is so-called an anonymous function and the
arrayfun(<function>, <array>)
maps the function over the given array.

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.

MATLAB: Pass part of structure field name to function

I need to pass a part of a structure's name into a function.
Examples of a available structs:
systems.system1.stats.equityCurve.relative.exFee
systems.system1.stats.equityCurve.relative.inFee
systems.system2.stats.equityCurve.relative.exFee
systems.system2.stats.equityCurve.relative.inFee
systems.system1.returns.aggregated.exFee
systems.system1.returns.aggregated.inFee
systems.system2.returns.aggregated.exFee
systems.system2.returns.aggregated.inFee
... This goes on...
Within a function, I loop through the structure as follows:
function mat = test(fNames)
feeString = {'exFee', 'inFee'};
sysNames = {'system1', 'system2'};
for n = 1 : 2
mat{n} = systems.(sysNames{n}).stats.equityCurve.relative.(feeString{n});
end
end
What I like to handle in a flexible way within the loop is the middle part, i.e. the part after systems.(sysNames{n}) and before .(feeString{n}) (compare examples).
I am now looking for a way to pass the middle part as an input argument fNames into the function. The loop should than contain something like
mat{n} = systems.(sysNames{n}).(fName).(feeString{n});
How about using a helper function such as
function rec_stru = recSA(stru, field_names)
if numel(field_names) == 1
rec_stru = stru.(field_names{1});
else
rec_stru = recSA(stru.(field_names{1}), field_names(2:end));
end
This function takes the intermediate field names as a cell array.
This would turn this statement:
mat{n} = systems.(sysNames{n}).stats.equityCurve.relative.(feeString{n});
into
mat{n} = recSA(systems.(sysNames{n}), {'stats', 'equityCurve', 'relative', feeString{n}});
The first part of the cell array could then be passed as an argument to the function.
This is one of those cases where matlab is a bit unhelpful in the documentation. There is a way to use the fieldnames function in matlab to get the list of all the fields and iterate over that using dynamic fields.
systems.system1.stats.equityCurve.relative.exFee='T'
systems.system1.stats.equityCurve.relative.inFee='E'
systems.system2.stats.equityCurve.relative.exFee='S'
systems.system2.stats.equityCurve.relative.inFee='T'
systems.system1.returns.aggregated.exFee='D'
systems.system1.returns.aggregated.inFee='A'
systems.system2.returns.aggregated.exFee='T'
systems.system2.returns.aggregated.inFee='A'
dynamicvariable=fieldnames(systems.system1)
This will return a cell matrix of the field names which you can use to iterate over.
systems.system1.(dynamicvariable{1})
ans =
equityCurve: [1x1 struct]
Ideally you would have your data structure fixed in such a way that you know how many levels of depth are in your data structure.

Looping through documents in matlab

I am attempting to loop through the variable 'docs' which is a cell array that holds strings, i need to make a for loop that colllects the terms in a cell array and then uses command 'lower' and unique to create a dictionary.
Here is the code i've tried sp far and i just get errors
docsLength = length(docs);
for C = 1:docsLength
list = tokenize(docs, ' .,-');
Mylist = [list;C];
end
I get these errors
Error using textscan
First input must be of type double or string.
Error in tokenize (line 3)
C = textscan(str,'%s','MultipleDelimsAsOne',1,'delimiter',delimiters);
Error in tk (line 4)
list = tokenize(docs, ' .,-');
Generically, if you get an "must be of type" error, that means you are passing the wrong sort of input to a function. In this case you should look at the point in your code where this is taking place (here, in tokenize when textscan is called), and doublecheck that the input going in is what you expect it to be.
As tokenize is not a MATLAB builtin function, unless you show us that code we can't say what those inputs should be. However, as akfaz mentioned in comments, it is likely that you want to pass docs{C} (a string) to tokenize instead of docs (a cell array). Otherwise, there's no point in having a loop as it just repeatedly passes the same input, docs, into the function.
There are additional problems with the loop:
Mylist = [list; C]; will be overwritten each loop to consist of the latest version of list plus C, which is just a number (the index of the loop). Depending on what the output of tokenize looks like, Mylist = [Mylist; list] may work but you should initialise Mylist first.
Mylist = [];
for C = 1:length(docs)
list = tokenize(docs{C}, ' .,-');
Mylist = [Mylist; list];
end

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.