Matlab: pass 'who' output on as argument - matlab

I have written a function that takes the names and values of the input variables and writes them to a file. eg.
a = 10;
b = 100;
writevars('file.txt',a,b);
gives me a file file.txt that contains:
\def\a{\num{10}}
\def\b{\num{100}}
It would now like to be able to pass on all variables that are found using the who command. Eg if who returns:
a b z
I would like to be able to use writevars as if I called writers('file.txt', a, b, z).
The main problem I have is that writevars makes use of inputname... (temporary variables won't work e.g. writevars('file.txt', 100) doesn't work since there is no name to be given in the file).
ANSWER
var_names = who;
for i = 1 : length(var_names)
evalin('caller',['writevars(''file.txt'', ' char(var_names(i)) ' )']);
end

You can use EVALIN to run who from within writevars, e.g.
function writevars(filename,varargin)
%# get a list of variable names in the calling workspace and read their values
if isempty(varargin)
listOfVars = evalin('caller','who');
values = cell(size(listOfVars));
for i=1:length(listOfVars)
values{i} = evalin('caller',listOfVars{i});
end
else
%# use inputname to read the variable names into listOfVars
end
%# --- rest of writevars is here ---

It can be used by using the return value of whos command:
function GetAllVars
a = 45;
x = 67;
ff = 156;
z = who();
for i=1:numel(z)
if ~isequal(z{i},'z')
fprintf(1,'%s = %f\n',z{i},eval(z{i}));
end
end

Related

Swap variable names and field names in a set of structs, so the field names become the struct names and vice versa?

I have a set of structs that all have the same field names. For example structs A, B, and C all have field names name and section. Is there a way to rearrange this organization of data so that the data goes from:
A.name = 'bb';
A.section = 199;
B.name = 'joe';
B.section = 101;
C.name = 'rob';
C.section = 33;
to this:
name =
A: 'bb'
B: 'joe'
C: 'rob'
section =
A: 199
B: 101
C: 33
The current code I have, for example, operates like this:
% ORIGINAL STRUCTS
A.name = 'bb';
A.section = 199;
B.name = 'joe';
B.section = 101;
C.name = 'rob';
C.section = 33;
% CREATE VARIABLE NAMES FOR NEW STRUCTS
oldFNames = fieldnames(A); % old field names
oldVNames{1} = varname(A); % old variable names
oldVNames{2} = varname(B);
oldVNames{3} = varname(C);
% RESTRUCTURE STRUCTS (SWITCH FIELDNAMES AND VARIABLE NAMES)
for j = 1:length(oldFNames)
for k = 1:length(oldVNames)
eval([oldFNames{j} '.' oldVNames{k} ' = ' oldVNames{k} '.' oldFNames{j}]);
end
end
function out = varname(var) % Function to get variable name
out = inputname(1);
end
I find the hack to use the varname function to be not great, and I don't know whether there is a way to make it easily adaptable to the number of variables I have. Any input on how to simplify this procedure would be great. Thanks.
It would be easier to do it all in a function, instead of just using a function to get the input variable name. Here's one solution:
function invert_struct(varargin)
varNames = arrayfun(#inputname, 1:nargin, 'UniformOutput', false); % Get input names
s = [varargin{:}]; % Combine inputs into a structure array
for f = fieldnames(s).' % Loop over fields
assignin('caller', f{:}, cell2struct({s.(f{:})}, varNames, 2));
end
end
And you would call it like so, with however many inputs you like:
invert_struct(A, B, C, ...);
The function uses assignin to create your new variables in the calling function and cell2struct to create a new structure from your field data and old variable names. Note that it also makes use of dynamic field names.

Linking input file with variable stored in it to several function files

I have code which is in multiple function files, input to these functions are stored in one file called inputfile.m(script file), in which I assigned some constant values to the inputs. These values act as a input to several function files named degree_eq.m(function file).
How I can write the code so that every time of execution, function files takes the required inputs from the inputfile.m.
Let's say you have two functions, one with your inputs (inputfile) and one where you do stuff (do_stuff).
function [a,b,c] = inputfile()
%define your constants
a=10;
b=100;
c=8.3;
function z = do_stuff()
[a, b, c] = inputfile() %takes the inputs from inputfile.m
z = a*c - b;
You can exploit the fact that matlab variables are persistent outside their scope. Lets say you have 6 constants a,b,c,d,e,f defined in input file. So what can be done is, write a top script called top.m which would be something like
inputfile
degree_eq1(a,b,c)
degree_eq2(c,d,e)
A third approach (combining Nirvedh Meshram and qbzenker answers) is to call an input script inside your MATLAB functions.
The advantage is that you do not have to specify which parameters are needed from or specified in your input script, but this is a disadvantage too, because the needed inputs are not made explicit. So, it is much more error prone. I only recommend this approach for a large number of input variables.
inputfile.m:
a = 5;
b = 8;
c = 10;
degree_eq.m:
function d = degree_eq()
inputfile;
d = a + b + c;
end
As an alternative, you can specify which input file to use:
degree_eq.m:
function d = degree_eq(inputFilename)
eval(inputFilename);
d = a + b + c;
end
and call it as follows:
degree_eq('inputfile');

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

How to use file name to sort and count files stored in a .mat file?

dbhole.mat file contains files name like: d1h1,d1h2,d1h3,d1h4,d2h1,d2h2,d3h1,d3h2,d3h4,d3h5,d3h6.
I want to count the number of files having a name that starts with d1 then d2 ,d3 and so on in a loop.
If you mean that you want to get a list of the variables in a *.mat file that start with d1, d2, etc. You could use who and matfile to get a list of all variables. who accepts a regular expression which you can create specific to the variables you want to see.
matobj = matfile('filename.mat');
d1vars = who(matobj, '-regexp', '^d1h');
nD1 = numel(d1vars);
Or more generally in a loop
for k = 1:3
vars{k} = who(matobj, '-regexp', ['^d', num2str(k), 'h']);
% And get the number
nVars(k) = numel(vars{k});
end
If you have an older version of MATLAB, you can load the file into a struct and then check the fields of that struct for the pattern that you'd like.
data = load('filename.mat');
variables = fieldnames(data);
isd1 = variables(~cellfun(#isempty, regexp(variables, '^d1h')));
nD1 = numel(isd1);

MATLAB - Cleanly read variables out of a function possibly using some type of varargout...?

I have function f1 which must contain subfunctions, so I can't use another script:
function vars = f1()
a = 1;
b = 'hello';
c = {[1 2 3]};
currvars = whos; %all variable info
for k = 1:size(currvars, 1)
eval(['vars.(currvars(k).name) = ' currvars(k).name ';']);
end
end
I call the function in a script, and then I create the variables in the script using genvarname() and eval():
vars = f1();
varnames = genvarname(fieldnames(vars));
for k = 1:size(varnames(:),1) %Creates vars with the struct's fieldnames.
eval([varnames{k} ' = vars.' varnames{k} ';']);
end
clearvars vars varnames
I'd like to fit the variable creation process into a function somehow while reading out all the variables only to the script calling it, but I don't want to assign a hundred different variable names to the output. Does anyone have any advice on how to do this?
DON'T CREATE zillions of automatically named variables. This is foolish and terribly poor programming style. Instead, learn to use arrays. Multidimensional arrays, cell arrays, struct arrays.
Or, do what you have done, and then be forced to find a kludge like you are looking for.
Take your pick. Eval is evil.
You could return a structure with "corrected" fieldnames:
function output = someFunc
vars = f1();
protected = { %# some list of varnames you don't want
};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
output.(newnames{k}) = vars.(names{k});
end
end
If you then use
output = someFunc;
varnames = fieldnames(output);
for k = 1:numel(fieldnames)
eval([varnames{k} ' = output.' varnames{k} ';']);
end
in the script/function where you want the variable names, you have a relatively clean way of locking everything up in the function someFunc without having to pre-define all output variable names.
You can also do this in one step:
function someFunc2
vars = f1();
protected = { %# some list of varnames you don't want
};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
assignin('caller', newnames{k}, vars.(names{k}));
end
end
Which means you just call the function
someFunc2;
in your script, and the function then defines and assigns all the variables in the script's workspace.
A tiny step forward, but forward nonetheless :)
CREDIT TO RODY...
#Old semi-"global" variables:
function vars = f1()
a = 1;
b = 'hello';
c = {[1 2 3]};
currvars = whos; %all variable info
for k = 1:size(currvars, 1)
eval(['vars.(currvars(k).name) = ' currvars(k).name ';']);
end
end
#Function to assign variables to the calling script's/function's workspace. Variable names are determined by the single structure's fieldnames:
function setvars(func)
vars = func;
protected = {'If needed, put variable names you do not want here'};
names = fieldnames(vars);
newnames = genvarname(names, protected);
for k = 1:numel(newnames)
assignin('caller', newnames{k}, vars.(names{k}));
end
end
#Script call:
setvars(f1);