Optional input arguments on Matlab function - matlab

I need to implement a function that does some image processing on a specific number of images (nFrames) that are located in a folder (folder1). The function would look something like:
function imgProc( nFrames,path )
Let's say I have several folders with different numbers of images in each one. What I need to have is optional input arguments, meaning that if the user wants, he can do the image processing for the first 10 images, for example, but if he does not specify the number, the function should perform the task on all the images. And the same for the folders, there should be a default folder in case the user does not specify from which folder he wants to take the images. It also could be interesting that the user could call the function with 0, 1 or 2 input arguments.
I have thought of using the exist function like this:
function imgProc( nFrames,path )
if exist( path,'var' ) == 0
path = 'img/record_space';
end
if exist( nFrames,'var' ) == 0
d = dir([ path,'\*.png' ]);
nFrames = length( d( not([ d.isdir ]) ) );
end
end
But if I call the function with no input arguments it gives an error saying there's not enough input arguments.
Is it possible to create a function that can have all of its arguments optional and moreover allow you to input 0, 1 or 2 according to your needs, taking into account that one is a number and the other one a string?

To fix the problem in your code:
function imgProc( nFrames,path )
if exist( 'path','var' ) == 0
path = 'img/record_space';
end
if exist( 'nFrames','var' ) == 0
d = dir([ path,'\*.png' ]);
nFrames = length( d( not([ d.isdir ]) ) );
end
end
exists expects the variable name, not the variable itself. You can pass a variable containing a string, but then it would check if that string exists:
x='y'
exist(x,'var') % checks if y exists
exist('x','var') %checks if x exists
What I recommend to have a flexible interface is using the inputParser
function imgProc( varargin )
p = inputParser;
addOptional(p,'frames',inf,#isnumeric);
addOptional(p,'path',pwd,#(x)exist(x,'dir'));
parse(p,varargin{:});
%lower frames if required to the maximum possible value
frames=min(p.Results.frames,numel(dir(fullfile(p.Results.path,'*.png'))));
%if frame was previously a number (not inf) and is lowered, print a warning.
if frames<p.Results.frames&&p.Results.frames~=inf
warning('parameter frames exceeded number of images present. Frames set to %d',frames);
end
disp(p.Results);
end
Possible ways to call the function:
>> imgProc
frames: Inf
path: 'D:\Documents\MATLAB'
>> imgProc('frames',1)
frames: 1
path: 'D:\Documents\MATLAB'
>> imgProc('path','foo')
frames: Inf
path: 'foo'
>> imgProc('path','bar','frames',9)
frames: 9
path: 'bar'

In newer versions on Matlab, you can also call the function using this syntax, e.g.:
imgProc()
imgProc( frames=1 )
imgProc( path="foo" )
imgProc( path="bar", frames=9 )
The result will be the same as Daniel's answer above, but it makes the function calling more intuitive (in my opinion).

Related

How to display an array of objects as will?

I have defined a class like
classdef Test
properties
a
b
end
methods
function this = Test(a, b)
this.a = a;
this.b = b;
end
function disp(this)
fprintf('a=%d b=%d\n', this.a, this.b);
end
end
end
But when I want to display a vector of Test, it seems not print each elements of array using the disp function just defined.
>> out = [Test(1,2),Test(3,4)]
out =
a=1 b=3
a=2 b=4
The questions is how to display an array of objects appropriately? Is there a way to overload the disp function and print as the following:
out=
a=1 b=2
a=3 b=4
(In my considering , the output will be same as calling disp function to element of array one by one.. But the output seems like firstly print all the a's value 1 3 and then b's value 2 4.)
You are getting this result because in your statement out = [Test(1,2),Test(3,4)], the variable out becomes an array of the same class Test, but of size [1x2].
If you try out.a in your console, you'll get:
>> out.a
ans =
1
ans =
3
This is a coma separated list of all the values of a in the out array. This is also the first parameter that your custom disp function sees. It then sees another column vector of all the values of b. To understand what the function fprintf is presented with you can also try in your console:
>> [out.a,out.b]
ans =
1 3 2 4
>> [out.a;out.b]
ans =
1 3
2 4
Since fprintf works in column major order, it will consume all the values column wise first. In that case we can see that the last option we tried seems better.
Indeed, if you change your disp function to:
function disp(this)
fprintf('a=%d b=%d\n', [this.a ; this.b]);
end
You get the desired output:
>> out = [Test(1,2),Test(3,4),Test(5,6)]
out =
a=1 b=2
a=3 b=4
a=5 b=6
Whichever size of object array you define. Just keep in mind that if you input an array of Test object they will be considered column wise:
>> out = [ Test(1,2),Test(3,4) ; Test(5,6),Test(7,8) ]
out =
a=1 b=2
a=5 b=6
a=3 b=4
a=7 b=8
Last option, if you want even more granularity over the display of your object array, you can customise it the way you like inside the disp function:
function disp(this)
nElem = numel(this) ;
if nElem==1
fprintf('a=%d b=%d\n', this.a , this.b );
else
for k=1:nElem
fprintf('a=%d b=%d\n', this(k).a , this(k).b);
end
end
end
This produces the same display than before, but since the elements are treated one by one, you could customise even further without having to consider the way arrays are treated by fprintf.
With the syntax you use, you should overload the display function instead of the disp function.
See the (not that simple to read) corresponding page in the documentation.

Function with different return variables

Is there a way to have one function that can return two different variables, but only one at a time AND knowing which one is returned in the function call?
example:
I have the following function in which only one of the outputs is valid (the other one would be [])
function [a,b] = AlternatingOutput (input)
if input == 1
return ONLY A
else
return ONLY B
end
end
and i call it in a script
[a,b] = AlternatingOutput (input)
i want a way to say the following (pseudocode):
if (function outputs a)
[a,~] = AlternatingOutput(input)
elseif (function outputs b)
[~,b] = AlternatingOutput(input)
end
the script is run in a loop, and later i need the newest Valid values for a and b, so i cannot overwrite one of the two with []
I do understand that I could just write a function that checks which variable will be output, but I was wondering if there is a more elegant way.
I hope I have made my question clear, and I hope someone can answer me :)
There is no way to tell if an output argument is actually used. You may check the number of output arguments using nargout and it would allow to distinguish between [a] = AlternatingOutput(input) and [~,b] = AlternatingOutput(input)
I don't know the full context of your problem, but maybe you can put all your variables into a struct? Simply pass this struct everytime you call the function and let it decide which variables to manipulate. (This might be slow in some programming languages, but not in matlab).
How about retuning a cell?
function [ ab ] = testfun( input )
if input
ab={'ax'};
else
ab={2};
end
end
No worries about what is in the cell.
thb you could return what ever you want, Matlab does not check the type anyways
If only one of the outputs from the function AlternatingOutput is valid, then you only need to return one output:
function [X] = AlternatingOutput(input)
if input == 1
X = A;
else
X = B;
end
end
To allocate the retured value to either a or b in the loop, put them into a cell:
C = {AlternatingOutput(1), AlternatingOutput(2)};
and then use input to determine which value is change. If input is either 1 or 2 you can just do
for counter = ...
input = mod(input,2)+1;
C{input}=AlternatingOutput(input);
end
If your function doesn't mind accepting more input variables, why not pass a and b as input:
function [a,b] = AlternatingOutput(a,b,input)
if input == 1
a = new_value_for_a;
% b retains its former value
else
% a retains its former value
b = new_value_for_b;
end
end
Then it can be easily called from your script in a loop:
for i= ...
[a,b] = AlternatingOutput(a,b,input);
...
...
end

Multiple commands in one, Matlab

Sometimes it is desired to make several calls in one command. A simple example could be strrep. Assume you want to replace all parentheses with brackets, all commas with dots and then remove all double quotations. The following pseudo code could then be desired:
strrep(myString, '()', '[]', ',', '.', '"', '')
Is there any way to accomplish this? You could of course go with:
strrep(strrep(strrep(myString, '()', '[]'), ',', '.'), '"', '')
Or save the strings in a cell array and use this in a for loop, but both solutions are incredibly ugly.
The most desired answer, is one that is generic for all functions that work in a similar way.
To directly answer your question, there is really no consistent way of doing this, no. It really depends on the function. If you search the documentation you will often find a way to do this. With strings, at least, you can usually pass cell arrays in place of strings to perform operations on multiple strings, and in this case multiple operations on the same string.
A Solution for This Particular Example
You can easily use regexprep to do this for you. You can pass a cell array of the expressions to match with a corresponding cell array of the replacement values.
regexprep('abc', {'a', 'b', 'c'}, {'1', '2', '3'});
%// '123'
For your specific example, you would do something like:
regexprep(myString, {'\(\)', ',', '"'}, {'[]', '.', ''})
And as an example:
myString = 'This, is a () "string"';
regexprep(myString, {'\(\)', ',', '"'}, {'[]', '.', ''})
%// 'This. is a [] string'
If you don't want to worry about escaping all of the expressions to be regex-compatible, you can use regexptranslate to do that for you.
expressions = regexptranslate('escape', {'()', ',', '"'});
regexprep(myString, expressions, {'[]', '.', ''});
Say you want function foo to work like this:
foo(Variable,Parameter1,Value1);
foo(Variable,Parameter1_1,Value1,Parameter2,Value2,...);
then using recursion:
function[Variable]=FooBar(Variable,varargin)
N=nargin-1; %\\ Count the input parameters
if N>=2
Parameter=varargin{1};
Value=varargin{2};
% Process the first Parameter-value pair
Variable=FooBar(Variable,varargin{3:N}); %\\ Cut first Parameter-Value pair off and pass the rest to foo again
end
This approach allows you to use chain of single parameters, pairs, triplets, quadruplets, etc.
In this perticullar example the pairs are executed as LIFO stack and last unpaired Parameter is ignored. You can also add some conditions to implement foo(IN,Parameter1,Value1,Modifier,Parameter2,Value2,...) and many other properties...
For your perticullar example:
function[MyString]=FooBar(MyString,varargin)
N=nargin-1; %\\ Count the input parameters
if N>=2
Parameter=varargin{1};
Value=varargin{2};
MyString=regexprep(MyString,Parameter,Value)
MyString=FooBar(MyString,varargin{3:N});%\\ Cut first Parameter-Value pair off and pass the rest to foo again
end
Examples:
>> myString='This, is a () "string"';
FooBar(myString,'()','[]','"','',',','.')
ans = This. is a [] string
>> myString='This, is a ("string")';
FooBar(myString,'()','[]','"','',',','.')
ans = This. is a (string)
>> myString='This, is a ("string")';
FooBar(myString,'(','[',')',']','"','',',','.')
ans = This. is a [string]
As already said by #Suever your example can be solved by regexprep and #thewaywewalk has hinted that there is no "general" soluction for all function calls.
Note I do not advocate this as a good way to code -> but its a quirky question and thus here is a suitable quirky solution....
There is lots of reason why you shouldn't do this - namely a nightmare to debug but you could in theory do this with an "intelligent" self calling function...
% Create your own function which takes the following inputs:
% fHandle - function handle to the function of choice
% property - your starting variable
% varargin - a cell array (or single var) of variables to
% pass into the fHandle on each call
% see examples below...
function output = multipleCalls ( fHandle, property, varargin )
% call your primary function using feval and your inputs
% with the 1st group of inputs from the 1st varargin
if iscell ( varargin{1} )
output = feval ( fHandle, property, varargin{1}{:} );
else
output = feval ( fHandle, property, varargin{1} );
end
% remove the varargin variable which has just been used.
varargin(1) = [];
% are they aremore multiple call?
if ~isempty ( varargin )
% if so self call to apply the subsequent calls.
output = multipleCalls ( fHandle, output, varargin{:} );
end
end
% modifying your example to use this method:
multipleCalls( #strrep, 'This, is a () "string"', { '()', '[]' }, { ',', '.' }, { '"', '' } )
% Its probably a longer command and is it any clearer -> probably not...
% Here is another example:
% Create a silly anonymous function
sillyFunction = #(a,b) a + b
% Then you can use it in the same way:
% Where 0 is what you start with and then
% each time you want to add 1, then 2, then 3 and finally 4
multipleCalls ( sillyFunction, 0, 1, 2, 3, 4 )

Create (static) handle array from multiple dynamic functions

I am new to Matlab and I have the following problem:
A function expects an input parameter of an array of function-handles
handleArray = #( param ) [ ...
#calcSumOfParam ; ... % and so on..
#calcSumOfParam ];
solution = calculateFunc( handleArray );
However, calcSumOfParam() actually needs more/additional input parameters (not only param) and is kind of heavy-structured (only an example here)
function [ sumOfParam ] = calcSumOfParam( param , maxIter , startIter )
sumOfParam = 0;
for iter = startIter : maxIter
sumOfParam = sumOfParam + param( iter );
end
end
Is there a way to do this?
I cannot use anonymous functions as I need to use loops and conditions. Also multiple functions won't work either, as I do not know the size of the handleArray and so the amount of functions (get it through user input).

Access complex matlab struct with function/string

I have a matlab struct which several levels (e.g. a.b(j).c(i).d). I would like to write a function which gives me the fields I want. If the struct has only one level, it would be easy:
function x = test(struct, label1)
x = struct.(label1)
end
E.g. if I have the struct a.b I could get b via: test('b'). However, this does not work with subfields, if I have a struct a.b.c I can't use test('b.c') to access it.
Is there any way to pass a string with the full field name (with dots) to a function to retrieve this field? Or is there even a better way to get only the fields that I select through the function arguments?
The goal? Sure, it would be a useless function for one fieldname, but I wan't to pass a list of fieldnames as argument to receive exactly these fields.
You should use subsref function:
function x = test(strct, label1)
F=regexp(label1, '\.', 'split');
F(2:2:2*end)=F;
F(1:2:end)={'.'};
x=subsref(strct, substruct(F{:}));
end
To access a.b.c you can use:
subsref(a, substruct('.', 'b', '.', 'c'));
The test function first splits the input using .as a delimiter and creates a cell array F where every other element is filled with . and then its elements are passed to substruct as arguments.
Note that if there are arrays of structs involved it will get the first one. For a.b(i).c(j).d passing b.c.d will return a.b(1).c(1).d. See this question for the way it should be handled.
As a side note, I renamed your input variable struct to strct because struct is a built-in MATLAB command.
One way is to create a self calling function to do this:
a.b.c.d.e.f.g = 'abc'
value = getSubField ( a, 'b.c.d.e.f.g' )
'abc'
function output = getSubField ( myStruct, fpath )
% convert the provided path to a cell
if ~iscell(fpath); fpath = strread ( fpath, '%s', 'delimiter', '.' ); end
% extract the field (should really check if it exists)
output = myStruct.(fpath{1});
% remove the one we just found
fpath(1) = [];
% if fpath still has items in it -> self call to get the value
if isstruct ( output ) && ~isempty(fpath)
% Pass in the sub field and the remaining fpath
output = getSubField ( output, fpath );
end
end