How to Give int-string-int Input as Parameter for Matlab's Matrix? - matlab

I would like to have short-hand form about many parameters which I just need to keep fixed in Matlab 2016a because I need them in many places, causing many errors in managing them separately.
Code where the signal is 15x60x3 in dimensions
signal( 1:1 + windowWidth/4, 1:1 + windowWidth,: );
Its pseudocode
videoParams = 1:1 + windowWidth/4, 1:1 + windowWidth,: ;
signal( videoParams );
where you cannot write videoParams as string but should I think write ":" as string and everything else as integers.
There should be some way to do the pseudocode.
Output of 1:size(signal,3) is 3 so it gives 1:3. I do not get it how this would replace : in the pseudocode.
Extension for horcler's code as function
function videoParams = fix(k, windowWidth)
videoParams = {k:k + windowWidth/4, k:k + windowWidth};
end
Test call signal( fix(1,windowWidth){:}, : ) but still unsuccessful giving the error
()-indexing must appear last in an index expression.
so I am not sure if such a function is possible.
How can you make such a int-string-int input for the matrix?

This can be accomplished via comma-separated lists:
signal = rand(15,60,3); % Create random data
windowWidth = 2;
videoParams = {1:1+windowWidth/4, 1:1+windowWidth, 1:size(signal,3)};
Then use the comma-separated list as such:
signal(videoParams{:})
which is equivalent to
signal(1:1+windowWidth/4, 1:1+windowWidth, 1:size(signal,3))
or
signal(1:1+windowWidth/4, 1:1+windowWidth, :)
The colon operator by itself is shorthand for the entirety of a dimension. However, it is only applicable in a direct context. The following is meaningless (and invalid code) as the enclosing cell has no defined size for its third element:
videoParams = {1:1+windowWidth/4, 1:1+windowWidth, :};
To work around this, you could of course use:
videoParams = {1:1+windowWidth/4, 1:1+windowWidth};
signal(videoParams{:},:)

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.

Creating a function with variable number of inputs?

I am trying to define the following function in MATLAB:
file = #(var1,var2,var3,var4) ['var1=' num2str(var1) 'var2=' num2str(var2) 'var3=' num2str(var3) 'var4=' num2str(var4)'];
However, I want the function to expand as I add more parameters; if I wanted to add the variable vark, I want the function to be:
file = #(var1,var2,var3,var4,vark) ['var1=' num2str(var1) 'var2=' num2str(var2) 'var3=' num2str(var3) 'var4=' num2str(var4) 'vark=' num2str(vark)'];
Is there a systematic way to do this?
Use fprintf with varargin for this:
f = #(varargin) fprintf('var%i= %i\n', [(1:numel(varargin));[varargin{:}]])
f(5,6,7,88)
var1= 5
var2= 6
var3= 7
var4= 88
The format I've used is: 'var%i= %i\n'. This means it will first write var then %i says it should input an integer. Thereafter it should write = followed by a new number: %i and a newline \n.
It will choose the integer in odd positions for var%i and integers in the even positions for the actual number. Since the linear index in MATLAB goes column for column we place the vector [1 2 3 4 5 ...] on top, and the content of the variable in the second row.
By the way: If you actually want it on the format you specified in the question, skip the \n:
f = #(varargin) fprintf('var%i= %i', [(1:numel(varargin));[varargin{:}]])
f(6,12,3,15,5553)
var1= 6var2= 12var3= 3var4= 15var5= 5553
Also, you can change the second %i to floats (%f), doubles (%d) etc.
If you want to use actual variable names var1, var2, var3, ... in your input then I can only say one thing: Don't! It's a horrible idea. Use cells, structs, or anything else than numbered variable names.
Just to be crytsal clear: Don't use the output from this in MATLAB in combination with eval! eval is evil. The Mathworks actually warns you about this in the official documentation!
How about calling the function as many times as the number of parameters? I wrote this considering the specific form of the character string returned by your function where k is assumed to be the index of the 'kth' variable to be entered. Array var can be the list of your numeric parameters.
file=#(var,i)[strcat('var',num2str(i),'=') num2str(var) ];
var=[2,3,4,5];
str='';
for i=1:length(var);
str=strcat(str,file(var(i),i));
end
If you want a function to accept a flexible number of input arguments, you need varargin.
In case you want the final string to be composed of the names of your variables as in your workspace, I found no way, since you need varargin and then it looks impossible. But if you are fine with having var1, var2 in your string, you can define this function and then use it:
function str = strgen(varargin)
str = '';
for ii = 1:numel(varargin);
str = sprintf('%s var%d = %s', str, ii, num2str(varargin{ii}));
end
str = str(2:end); % to remove the initial blank space
It is also compatible with strings. Testing it:
% A = pi;
% B = 'Hello!';
strgen(A, B)
ans =
var1 = 3.1416 var2 = Hello!

Workaround equivalent of "inputname" to return structure name?

I know that, inside a MATLAB function, inputname(k) will return the k-th argument iff the argument is a variable name. Is there any way to write some parsing code that can retrieve the full input argument when that argument is a structure, e.g. foo.bar ? The reason I want to be able to do this is that I'm writing some tools for generic use where the input could be either a named variable or a named structure element.
My primary intent is to be able to store and return the input argment(s) as part of a structure or other variable that the function returns. This is a 'chain of custody' feature which makes it easier for me or others to verify the source data sets used to generate the output data sets.
I don't want the user to have to self-parse externally, or to have to deal with some kludge like
function doit(name,fieldname)
if(exist('fieldname','var'))
name = name.(fieldname);
myinput = [inputname(1),inputname(2)];
else
myinput = inputname(1);
end
% do the function stuff
(I call this a kludge because it both requires the user to enter strange arguments and because it fouls up the argument sequence for functions with multiple inputs)
There is no support from the language to get the input names when passing structs. The reason is probably x.a is internally a call to subsref which returns a new variable, all context is lost. The only possibility you have is using the debug tools and parse the code. There is no other option.
function x=f(varargin)
[ST, I] = dbstack('-completenames', 1);
if numel(ST)>0
fid=fopen(ST(1).file,'r');
for ix=2:ST(1).line;fgetl(fid);end
codeline=fgetl(fid);
fclose(fid);
fprintf('function was called with line %s\n',codeline);
else
fprintf('function was called from base workspace\n');
end
end
From there you may try to parse the code line to get the individual argument names.
Far uglier than Daniel's approach, and probably will crash on the wrong OS, but here's a hack that works to retrieve the first argument; easily adjusted to retrieve all arguments.
[~,myname] = system('whoami');
myname = strtrim(myname(4:end)); % removes domain tag in my Windows envir
% sorry about " \' " fouling up SO's color parsing
myloc = ['C:\Users\' , myname , '\AppData\Roaming\MathWorks\MATLAB\R2015a\History.xml'] ;
f = fopen(myloc,'r');
foo = fscanf(f,'%s');
fclose(f);
pfoo = findpat(foo,'myFunctionName');
% just look for the last instance
namstart = find(foo(pfoo(end):(pfoo(end)+30)) =='(',1) +pfoo(end);
% catch either ')' or ','
namend(1) = find(foo((namstart):end)== ')',1) -2 +namstart;
if numel(find(foo((namstart):end)== ',',1)),
namend(2) = find(foo((namstart):end)== ',',1) -2 +namstart;
end
thearg = foo(namstart:(min(namend)) );

matlab How to use a textstring as input parameter in functions

I would like to use a dataset filename "AUDUSD" in several functions. It would be easier for me, just to change the filename "AUDUSD" to a more general name like "FX" and then using the abbreviation "FX" in other_matlab functions, e.g. double(). But matlab does not know the name "FX" (that should be assigned to the dataset "AUDUSD") in the code below... Any suggestions?
CODE:
FX = 'AUDUSD';
load(FX); %OKAY !!! FX works as input to open file AUDUSD!
Svars = {'S_bid','S_offer'};
Fvars = {'F_bid','F_offer'};
vS = double(FX,Svars); % FX does NOT work as input for the file AUDUSD
There is no double() function that accepts multiple cell arrays as arguments (this is what happens when you call double(FX,Svars)).
If you call double(FX), then each character in FX is interpreted for its ASCII value and then cast to double. So you get [ 65.0 85.0 68.0 85.0 83.0 68.0 ]. This is the behavior for the double() function if you provide a vector: each individual value in the vector is cast to double.
You'd have to provide more details on what you're trying to accomplish to give any more suggestions.
I have a different example, maybe you will better understand my point. The key work I would like to process is as follows:
I have got a folder with "dataset" files. I would like to loop through this folder, entering in any datasetfile, extracting the 2nd and 3rd column of each dataset file, and constructing only ONE new datasetfile with all 2nd and 3rd columns of the datasetfiles.
One problem is that the size of the datasetfiles are not the same, so I tried to translate a datasetfile into a double-matrix and then consolidate all double matrices into ONE double matrx.
Here my code:
folder_string = 'Diss_Data/Raw';
FolderContent = dir(folder_string);
No_ds = numel(FolderContent);
for i = 1:No_ds
if isdir(FolderContent(i).name)==0
file_string = FolderContent(i).name;
file_path = strcat(folder_string,'/',file_string)
dataset_filename = file_string(1:6);
load(file_path); %loads the suggested datasetfile; OKAY
M = double(dataset_filename);% returns an ASCII code number; WRONG; should transfer the datasetfile into a matrix M
vS = M(:,2:3);
%... to be continued
end
end

Error using minus in MATLAB

temp(i,1) = rand(1)*(pb(1,num).pos(i,1) - pw(1,num).pos(i,1));
This line gives the following error:
Error using ==> minus
Not enough input arguments.
The following are the definitions of pb and pw.
pw=struct('fitness',[],'pos',{});
pb=struct('fitness',[],'pos',{});
pos is a 2 x 1 array.
When tracking down errors like this, I break the problem up into smaller bits. Especially when the logic isn't readily apparent. Not only does it provide a path that can be used to step through your function using the debugger, but it also makes it more readable.
I've taken liberty with the intermediate variable names.
thisPb = pb(1,num);
thisPw = pw(1,num);
initialPos= pw.pos(i,1);
finalPos = pb.pos(i,1);
whos initialPos finalPos
temp(i,1) = rand(1) * (finalPos - initialPos);
The line with whos will print out the values. Make sure that finalPos and initialPos are both numbers.
One way that you can get this error is when num is an empty matrix.
The expression
>> s(x).a
can return a variable number of outputs, depending on the size of x.
If x = [1,2,3] for example, it will return three values (as long as s has at least three elements).
If x = [] on the other hand, then s(x).a will return no outputs, so the expression
>> disp(s(x).a)
will give you a Not enough input arguments error, which is almost certainly what you're seeing. You should check that num is not empty.
Are you sure, that all values are really initialised? Try to check this before your codeline.
disp(pb(1,num).pos(i,1))
disp(pw(1,num).pos(i,1))
temp(i,1) = rand(1)*(pb(1,num).pos(i,1) - pw(1,num).pos(i,1));