I just want to make a script which runs multiple files and stores their outputs in separate log files.
So I wrote the code by using diary to generate the output, but the diary function is only 1 log file and the output is updating in the same log file for remaining iterations. In my testconfig_1 file, I have at present only print as the content.
Then I tried to use the fopen method, with this I am getting multiple log files but I don't understand how I can put that data into the log file which I have created through fopen after each run.
% with diary method
clear all;
diary on;
instring ='testconfig_';
for x = 1:3
fprintf ('Simulation on testconfig_%d \n' , x);
test = [instring num2str(x)];
run(test);
diary testconfig_(x).log;
end
% without diary method
clear all;
diary on;
instring ='testconfig_';
for x = 1:3
fprintf ('Simulation on testconfig_%d \n', x);
test = [instring num2str(x)];
run(test);
fid = fopen(sprintf('testconfig_%d.log',x),'w');
end
I wanted to get testconfig_1.log, testconfig_2.log, testconfig_3.log and I wanted to print in_testconfig_1, in_testconfig_2, in_testconfig_3 respectively
You are using command syntax to call the diary function.
% Command syntax
diary filename.log
% Equivalent function syntax
diary( 'filename.log' );
Notice that, when using command syntax, all arguments are treated as strings, despite not having any quote marks!
So when you do diary testconfig_(x).log, the equivalent is
diary( 'diary testconfig_(x).log' );
All of your logs have the same filename, because x is never evaluated as the loop variable, it's always just part of a string!
You are trying to create the strings with the loop variable in the name, for this you cannot use command syntax.
Instead, use function syntax like this:
filename = sprintf( 'diary testconfig_%d.log', x );
diary( filename ); % treat the filename variable as a variable, not a string
You don't have to declare the intermediate filename variable, and there are other ways to create the filename string, but I hope this demonstrates the issue.
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)) );
I got a this program which takes in all it data from a .txt file. It is possible to read the required data from the text file and pass that data to a function to work with? I have tried reading the data first and passing it to the function but then my plot refuses to work.
Right now I am doing it by sending in the name of the text file to the function and then read the data but this means that I am reading the data each time I call the function and I was hoping that I could just read the data once and then pass it on to the function. I think that not reading the data many times would speed up my program considerable.
My code looks like this
main.m
young bein_AB_light.txt %%calling the function with bein_AB_light.txt as parameter.
young.m
function young(filename)
fid = fopen(filename,'r');
C = textscan(fid,'%*f%*f%*f%*f%f');
fclose(fid);
Y=10500*C{1}.^2.29; %
plot(C{1},Y,'.K')
if(strfind(filename,'AB'))
xlabel('BMD[g/cm^3]');
ylabel('Youngstudull');
title('Reiknadur Youngstudull fyrir AB bein')
else
xlabel('BMD[g/cm^3]');
ylabel('Youngstudull');
title('Reiknadur Youngstudull fyrir SCI bein')
end
end
EDIT...
This is what I was trying but it gives me error when it tries to plot. Plot does not accept filename{1} to use as the X coordinites. I have also tried to use cell2mat function to change the input but that did not work.
main.m
fid = fopen(filename,'r');
AB_Bein = textscan(fid,'%*f%*f%*f%*f%f');
fclose(fid);
young AB_bein %%calling the function with AB_Bein as parameter.
young.m
function young(filename)
Y=10500*filename{1}.^2.29; %
plot(filename{1},Y,'.K')
if(strfind(filename,'AB'))
xlabel('BMD[g/cm^3]');
ylabel('Youngstudull');
title('Reiknadur Youngstudull fyrir AB bein')
else
xlabel('BMD[g/cm^3]');
ylabel('Youngstudull');
title('Reiknadur Youngstudull fyrir SCI bein')
end
end
it's possible that your problem is the way you are calling young.
If I create a function
function fileContents= young(filename)
fid = fopen(filename,'r');
C = textscan(fid,'%*f%*f%*f%*f%f');
fclose(fid);
fileContents=C{1};
and then call it using
fileContents= young('textfile.txt');
rather than
young textfile.txt
That brings the data from the file out into the variable named fileContents
I want to write a lazy mans command to output any variable I choose in the workspace as a comma delimited .txt file. I know you can use dlmwrite('outName.txt',varname); but I want something where I can simply go out(varname) and it does the same thing.
So far I have come up with this:
First function needed toget the varname as a string name
function out = strfromvar(input)
out = inputname(1);
end
Second function to dlmwrite that string name and variable...
function [out] = toigor(input)
stringName = strfromvar(input);
outName = [stringName '.txt'];
dlmwrite(outName,input);
end
The area I am stuck is at the outName area. I cant get it so it turns my chosen variable into a .txt file. It just calls it 'input'. The file works as anticipated but i'd liek the program to fully work. I am sure I am just missing a small bit here.
This is what does the trick for me:
function toigor(input)
stringName = inputname(1);
outName = [stringName '.txt'];
dlmwrite(outName,input);
end
Note that you only need 1 function.
Aside from parsing the function file, is there a way to get the names of the input and output arguments to a function in matlab?
For example, given the following function file:
divide.m
function [value, remain] = divide(left, right)
value = floor(left / right);
remain = left / right - value;
end
From outside the function, I want to get an array of output arguments, here: ['value', 'remain'], and similarly for the input arguments: ['left', 'right'].
Is there an easy way to do this in matlab? Matlab usually seems to support reflection pretty well.
EDIT Background:
The aim of this is to present the function parameters in a window for the user to enter. I'm writing a kind of signal processing program, and functions to perform operations on these signals are stored in a subfolder. I already have a list and the names of each function from which the user can select, but some functions require additional arguments (e.g. a smooth function might take window size as a parameter).
At the moment, I can add a new function to the subfolder which the program will find, and the user can select it to perform an operation. What I'm missing is for the user to specify the input and output parameters, and here I've hit the hurdle here in that I can't find the names of the functions.
MATLAB offers a way to get information about class metadata (using the meta package), however this is only available for OOP classes not regular functions.
One trick is to write a class definition on the fly, which contain the source of the function you would like to process, and let MATLAB deal with the parsing of the source code (which can be tricky as you'd imagine: function definition line spans multiple lines, comments before the actual definition, etc...)
So the temporary file created in your case would look like:
classdef SomeTempClassName
methods
function [value, remain] = divide(left, right)
%# ...
end
end
end
which can be then passed to meta.class.fromName to parse for metadata...
Here is a quick-and-dirty implementation of this hack:
function [inputNames,outputNames] = getArgNames(functionFile)
%# get some random file name
fname = tempname;
[~,fname] = fileparts(fname);
%# read input function content as string
str = fileread(which(functionFile));
%# build a class containing that function source, and write it to file
fid = fopen([fname '.m'], 'w');
fprintf(fid, 'classdef %s; methods;\n %s\n end; end', fname, str);
fclose(fid);
%# terminating function definition with an end statement is not
%# always required, but now becomes required with classdef
missingEndErrMsg = 'An END might be missing, possibly matching CLASSDEF.';
c = checkcode([fname '.m']); %# run mlint code analyzer on file
if ismember(missingEndErrMsg,{c.message})
% append "end" keyword to class file
str = fileread([fname '.m']);
fid = fopen([fname '.m'], 'w');
fprintf(fid, '%s \n end', str);
fclose(fid);
end
%# refresh path to force MATLAB to detect new class
rehash
%# introspection (deal with cases of nested/sub-function)
m = meta.class.fromName(fname);
idx = find(ismember({m.MethodList.Name},functionFile));
inputNames = m.MethodList(idx).InputNames;
outputNames = m.MethodList(idx).OutputNames;
%# delete temp file when done
delete([fname '.m'])
end
and simply run as:
>> [in,out] = getArgNames('divide')
in =
'left'
'right'
out =
'value'
'remain'
If your problem is limited to the simple case where you want to parse the function declaration line of a primary function in a file (i.e. you won't be dealing with local functions, nested functions, or anonymous functions), then you can extract the input and output argument names as they appear in the file using some standard string operations and regular expressions. The function declaration line has a standard format, but you have to account for a few variations due to:
Varying amounts of white space or blank lines,
The presence of single-line or block comments, and
Having the declaration broken up on more than one line.
(It turns out that accounting for a block comment was the trickiest part...)
I've put together a function get_arg_names that will handle all the above. If you give it a path to the function file, it will return two cell arrays containing your input and output parameter strings (or empty cell arrays if there are none). Note that functions with variable input or output lists will simply list 'varargin' or 'varargout', respectively, for the variable names. Here's the function:
function [inputNames, outputNames] = get_arg_names(filePath)
% Open the file:
fid = fopen(filePath);
% Skip leading comments and empty lines:
defLine = '';
while all(isspace(defLine))
defLine = strip_comments(fgets(fid));
end
% Collect all lines if the definition is on multiple lines:
index = strfind(defLine, '...');
while ~isempty(index)
defLine = [defLine(1:index-1) strip_comments(fgets(fid))];
index = strfind(defLine, '...');
end
% Close the file:
fclose(fid);
% Create the regular expression to match:
matchStr = '\s*function\s+';
if any(defLine == '=')
matchStr = strcat(matchStr, '\[?(?<outArgs>[\w, ]*)\]?\s*=\s*');
end
matchStr = strcat(matchStr, '\w+\s*\(?(?<inArgs>[\w, ]*)\)?');
% Parse the definition line (case insensitive):
argStruct = regexpi(defLine, matchStr, 'names');
% Format the input argument names:
if isfield(argStruct, 'inArgs') && ~isempty(argStruct.inArgs)
inputNames = strtrim(textscan(argStruct.inArgs, '%s', ...
'Delimiter', ','));
else
inputNames = {};
end
% Format the output argument names:
if isfield(argStruct, 'outArgs') && ~isempty(argStruct.outArgs)
outputNames = strtrim(textscan(argStruct.outArgs, '%s', ...
'Delimiter', ','));
else
outputNames = {};
end
% Nested functions:
function str = strip_comments(str)
if strcmp(strtrim(str), '%{')
strip_comment_block;
str = strip_comments(fgets(fid));
else
str = strtok([' ' str], '%');
end
end
function strip_comment_block
str = strtrim(fgets(fid));
while ~strcmp(str, '%}')
if strcmp(str, '%{')
strip_comment_block;
end
str = strtrim(fgets(fid));
end
end
end
This is going to be very hard (read: impossible) to do for general functions (think of things like varargin, etc). Also, in general, relying on variable names as a form of documentation might be... not what you want. I'm going to suggest a different approach.
Since you control the program, what about specifying each module not just with the m-file, but also with a table entry with extra information. You could document the extra parameters, the function itself, notate when options are booleans and present them as checkboxes, etc.
Now, where to put this? I would suggest to have the main m-file function return the structure, as sort of a module loading step, with a function handle that points to the subfunction (or nested function) that does the real work. This preserves the single-file setup that I'm sure you want to keep, and makes for a much more configurable setup for your modules.
function module = divide_load()
module.fn = #my_divide;
module.name = 'Divide';
module.description = 'Divide two signals';
module.param(1).name = 'left';
module.param(1).description = 'left signal';
module.param(1).required_shape = 'columnvector';
% Etc, etc.
function [value, remain] = my_divide(left, right)
value = floor(left / right);
remain = left / right - value;
end
end
When you can't get information from a programming langauge about its contents (e.g., "reflection"), you have to step outside the language.
Another poster suggested "regular expressions", which always fail when applied to parsing real programs because regexps cannot parse context free langauges.
To do this reliably, you need a real M language parser, that will give you access to the parse tree. Then this is fairly easy.
Our DMS Software Reengineering Toolkit has an M language parser available for it, and could do this.
Have you considered using map containers?
You can write your functions along these lines . . .
function [outMAP] = divide(inMAP)
outMAP = containers.Map();
outMAP('value') = floor(inMAP('left') / inMAP('right'));
outMAP('remain') = inMAP('left') / inMAP('right') - outMAP('value');
end
...and call them like this ...
inMAP = containers.Map({'left', 'right'}, {4, 5});
outMAP = divide(inMAP);
...and then simply examine tha variable names using the following syntax...
>> keys(inMAP)
ans =
'left' 'right'
inputname(argnum) http://www.mathworks.com/help/techdoc/ref/inputname.html .