Modify script from another script - matlab

I have a script that is run inside a loop (some constants are modified at each iteration). Is there a way to comment out a line of the script without modifying the .m file?
UPDATE:
Following the answer from Floris and Matthew Simoneau, I made a function trying to do the same thing (and it works). The skipLineParameter is a string referencing to a base workspace variable that has a value of 0 (don't skipline) or 1 (skipline) :
function skipline(skipLineParameter, parameter, default)
try
a = evalin('base', skipLineParameter);
if ~a
assignin('base', parameter, default);
end
catch
assignin('base', parameter, default);
end
end

This is a possible approach - using a condition that is set in the main program to decide whether to execute a particular line in the script.
If your main program is
for ii = 1:9
skipLine3 = (mod(ii,3)==0);
runSub
end
And runSub.m looks like this:
A = 1;
B = 2;
% modified lines to trap condition where 'skipLine3' doesn't exist:
if ~exist('skipLine3', 'var') skipMe = false; else skipMe = skipLine3; end
if ~skipMe, B=B*2; end
fprintf(1, "for iteration %d B is %d\n", ii, B)
Then the output will be:
for iteration 1 B is 4
for iteration 2 B is 4
for iteration 3 B is 2
for iteration 4 B is 4
for iteration 5 B is 4
for iteration 6 B is 2
for iteration 7 B is 4
for iteration 8 B is 4
for iteration 9 B is 2
As you can see - the skipLine3 parameter, which is set in the main loop (every third iteration), affects whether line 3 (B=B*2) is executed in the script.

I think what you're looking for is a function. Here's how to turn runSub into a function:
function runSub(ii,skip)
A = 1;
B = 2;
if ~skip, B=B*2; end
fprintf(1, 'for iteration %d B is %d\n', ii, B);
You can access it in the loop like this:
for ii = 1:9
skipLine3 = (mod(ii,3)==0);
runSub(ii,skipLine3)
end

Related

Return property directly when class is called (Matlab)

I have a class called foo with only property M,
classdef foo
properties
M
end
methods
function obj = foo(arg1)
M=arg1;
end
end
end
and I create the object:
F=foo(1)
In C++ it is possible, that when I call F, that I directly get the value of one chosen variable. In my case I would like to get F.M when I just write F. For example this would allow to write
size(F)
instead of writing
size(F.M)
or defining a method size for my class. Is there a way in MATLAB to achieve this?
Edit: In other words, whenever I write F, I want that MATLAB reads it as F.M.
Edit: I will clarify what I want to acchieve.
My class represents a matrix whose values are multivariate infinite sequences with compact support. Thus I have to do a lot of bookkeeping not to mix up all the indices. Things I want to do with my matrix:
Matrix multiplication.
Convolution.
Upsampling, downsampling.
Everything else which is possible in a vector/matrix space.
I thought this is easier to acchieve when I encapsulate all the meta-data (this are the indices of the 0^th entries of the sequence) together with the data.
Because my class is actually a matrix, most operations work on that class in the same way as on ordinary matrices. Therefore I do not want to code it all over again (Because of code-maintenance, less bugs, code-readability).
In C++ I could do it that way. It seems, my approach to that problem is the wrong one in MATLAB.
You have to overload the function size as I mentioned in my comment.
classdef foo
properties
M
end
methods
function obj = foo(arg)
obj.M = arg;
end
function varargout = size(obj, varargin)
if nargin == 1
varargout = size(obj.M);
elseif nargin == 2 && nargout == 1
varargout = size(obj.M, varargin{1})
else
error('Wrong number of input or output arguments.')
end
end
function ret = mtimes(varargin)
try
ret = varargin{1}.M * varargin{2};
catch
ret = varargin{1} * varargin{2}.M;
end
end
end
end
Console Output:
>> F=foo(0:3);
>> size(F)
ans =
1 4
>> size(F, 2)
ans =
4
>> F*(4:7).'
ans =
38
>> (4:7).'*F
ans =
0 4 8 12
0 5 10 15
0 6 12 18
0 7 14 21
I could continue but preparing the console output for StackOverflow is horrible...

Matlab - Do action after every line

Is there an elegant way to tell matlab to perform a predefined action after the execution of every line in a certain script? By elegant I mean no calling of the action after every line, but rather something like a simple command given at the start of the script.
Example:
Action --> disp('Performing Action');
script:
a = 1;
b = 2;
c = 3;
So the desirable outcome is that after each assignment (of a, b and c), the disp() command would be performed.
You can automatically create a modifed file that has the desired action included at the end of each line:
action = 'disp(''Performing Action'');'; %// action to be added at the end of each line
file = 'script.m'; %// original script
file_out = 'script_out.m'; %// modified script with action added
x = importdata(file); %// cell array of strings. Each line of the
%// original file is a string
x = strcat(x, {' ; '}, action); %// add action at the end of each string,
%// preceded with `;` in case the original line
%// didn't include that
fid = fopen(file_out, 'w');
fprintf(fid, '%s\n', x{:}); %// write output file
fclose(fid);
a = 1;
disp('Performing Action');
b = 2;
disp('Performing Action');
c = 3;
disp('Performing Action');
Or, if you can do this in a loop
for ii = 1:3
a(ii) = ii;
disp('Performing Action');
end
Actually making it output something after every line is not very matlab, but you could of course just loose all the semicolons and thus make it display all variables if you want to track where in the script you are.
I'd suggest a verbose switch in your code. Set it to 0 for no output and 1 for output (or use multiple levels if so desired)
if verbose > 0
disp('Performing Action');
end
This way you can easily switch the output on or off, depending on need.
For the code-reading and appending piece, see Louis Mendo's answer at https://stackoverflow.com/a/32137053/5211833
Here is my attempt. You can:
read the function line by line
execute each line, followed by your custom function.
NOTE
This won't work with functions containing for, if, etc..
You can eventually improve the code by passing a function handler with your custom action to runEachLine (and feval with that).
Here a code sample (partly based on this):
foo.m
function foo(args)
a = args{1};
b = 2;
c = a + b;
end
runEachLine.m
function runEachLine( mfile, args )
if nargin < 1
error('No script m-file specified.');
end
if ~strcmp(mfile(end-1:end),'.m')
mfile = [mfile '.m'];
end
if ~exist(mfile,'file')
error(['Cannot access ' mfile])
end
% Read function file
M = textread(mfile,'%s','delimiter','\n');
% Remove empty lines
M = M(~cellfun('isempty',M));
% Input arguments
assignin('base', 'args', args);
% Skipping first line: function [...] = func_name(...)
% Skipping last line : end
for k=2:length(M)-1
try
% Execute each line
evalin('base',M{k})
% Execute your custom function
disp(['Performing Action: ' M{k}]);
catch ME
error('RunFromTo:ScriptError',...
[ME.message '\n\nError in ==> ' mfile ' at ' num2str(k) '\n\t' M{k}]);
end
end
end
Usage:
>>runEachLine('foo.m', {4});
Result:
>> runEachLine('foo.m', {4})
Performing Action: a = args{1};
Performing Action: b = 2;
Performing Action: c = a + b;
>>
No, there is not.
What you present in your original question is just a simple usage of the = operator.
If you want to overload the default behaviour of MATLAB then you should consider creating a class and define the desired behaviour for each operator or function needed.

How to output matrix dimensions together with its content?

Is it possible to make GNU Octave to output matrix dimensions together with its content? For example, it should produce smth. like this:
octave:1> X = [1 2; 3 4]
X [2x2] =
1 2
3 4
octave:2> X(1,:)
ans [1x2] =
1 2
In MATLAB, create display.m in a folder called #double somewhere in your path with this content:
function display(v)
name = inputname(1);
if isempty(name)
name = 'ans';
end
s = num2cell(size(v));
fprintf('\n%s [%d%s] =\n\n', name, s{1}, sprintf('x%d', s{2:end}));
builtin('disp', v);
end
This way you override the display method for class double, and get exactly what you have described. However, this will not work for other classes like int8, logical or cell. You have to override the method for all classes you are interested in. Example:
>> A=ones(2,2,2)
A [2x2x2] =
(:,:,1) =
1 1
1 1
(:,:,2) =
1 1
1 1
While Mohsen's answer does the job indeed, I felt that a separate m-file is somewhat an overkill for this purpose (especially if you don't want to clutter your directory with additional m-files). I suggest using a local anonymous function one-liner instead (let's name it dispf), so here are its evolution phases :)
The basic anonymous function I came up with is:
dispf = #(x)fprintf('%s =\n\n%s\n', inputname(1), disp(x));
which is essentially equivalent to the output in the command window after entering statements (that do not end with a semicolon, of course). Well, almost... because if inputname returns an empty string, it doesn't print 'ans' (and it should). But this can be corrected:
dispf = #(x)fprintf('%s=\n\n%s\n', ...
regexprep([inputname(1), ' '], '^ $', 'ans '), ...
disp(x));
This is basically using regexprep to match an empty string and replace it with 'ans'. Finally, we append the dimensions after the variable name:
dispf = #(x)fprintf('%s%s =\n\n%s\n', ...
regexprep([inputname(1), ' '], '^ $', 'ans '), ...
strrep(mat2str(size(x)), ' ', 'x'), ...
disp(x));
Now you can plug this one-liner is into any script without the need for an additional m-file!
Example
Just a proof that it's working:
dispf = #(x)fprintf('%s%s =\n\n%s\n', ...
regexprep([inputname(1), ' '], '^ $', 'ans '), ...
strrep(mat2str(size(x)), ' ', 'x'), ...
disp(x));
A = [1 2; 3 4];
dispf(A)
dispf(A(1, :))
The result is as expected:
A [2x2] =
1 2
3 4
ans [1x2] =
1 2
I don't know if it works in Octave, but in MATLAB you can use format debug command and get the dimensions of the array and a bit more:
>> format debug
>> X = [1 2; 3 4]
X =
Structure address = 7d19498
m = 2
n = 2
pr = 373bafa0
pi = 0
1 2
3 4
Here is another way to do it. The advantage of this method is that it can deal with more complicated inputs than the mentioned alternatives.
function show(s)
t = regexp(s,'=');
if any(t)
evalin('caller',['disp(size(' s(t+1:end) ')),' s])
else
evalin('caller',['disp(size(' s ')),' s])
end
To use it, save the function and try this:
show x = rand(3)
show('y = {uint8(8);[6 7 8]}')
Note that it can take the convenient command syntax for simple inputs and that you need the function form with the command in string form for complicated inputs (containing semicolons or apostrophes).
Here is another one. You could either use it to overload #double/display as others have explained, or name it something else and use it as your own custom display function:
function display(x)
% determine whether format is loose or compect
loose = strcmp(get(0,'FormatSpacing'), 'loose');
% print name or ans
name = inputname(1);
if isempty(name), name = 'ans'; end
if loose, disp(' '); end
disp([name ' =']);
if loose, disp(' '); end
% print size
sz = size(x);
if length(sz) == 2
fprintf(' %s: %d-by-%d\n', class(x), sz(1), sz(2));
elseif length(sz) == 3
fprintf(' %s: %d-by-%d-by-%d\n', class(x), sz(1), sz(2), sz(3));
else
fprintf(' %s: %d-D\n', class(x), numel(sz));
end
if loose, disp(' '); end
% print array
disp(x);
end
Note that I changed the format of the output a little bit from what you had:
>> format compact;
>> x = magic(5);
>> display(x)
x =
double: 5-by-5
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9

MATLAB: Copying Global variable for all Workers

I want to pass "a" as a global variable to the function "tsfn", say
function [ out ] = tsfn( )
global a;
out=a+1;
end
When I run the following I get the expected result:
>> global a;
a=1
out=[];
for i=1:4
out =[out tsfn()];
end
out
a =
1
out =
2 2 2 2
However if I run it with parfor instead of for I end up with a blank vector. Which leads me to believe that "a" is not being passed into the function. I'm wondering if there is a way to pass the variable as a global variable for all workers.
Thanks
Works fine on my platform. Try just restarting your computer or Matlab. Generally, the "parfor" loop accomplishes the same task as the "for" loop--each loop is computed in parallel. Declaring "global" in one or more functions and/or the base workspace allows each of them to access the contents of the global variable, so your usage is correct.
Here is my code:
function[ out ] = tsfn()
global a;
out = a + 1;
end
EDU>> global a;
EDU>> a = 1;
EDU>> out = [];
EDU>> parfor i = 1 : 4
out = [ out tsfn() ];
end
EDU>> a
a =
1
EDU>> out
out =
2 2 2 2
Aside, a simple way to test the contents of a variable inside a function is to remove the semicolon, which prints it to the editor.

Using fprintf to print on several lines in Matlab

Question:
Write a procedure called Print7 to print all integer numbers within the range 0:100 that are divisible by 7. Ten numbers are to be printed on one output line. Hence write a program that invokes that procedure.
This is what I did
file = fopen('print7.dat','r');
x = 1:100
for x=[1:100]
if mod(x,7) == 0;
print7 = [x]
end
end
fprintf('print7 %d\n', print7)
Now it's output becomes the number 98 - which I understand to be the largest number under 100 divisible by 7. But I want a 10xn matrix-like result.
What do I do?
What you are doing stores your result in a variable and overwrites the variable in each iteration. You could print it directly instead like this:
c=0;
for x=[1:100]
if mod(x,7) == 0
fprintf('%3d',x)
c=c+1;
if mod(c,10) ==0
fprintf('\n')
end
end
end
fileID = fopen('print7.dat','r');
for x = 1:100
if(mod(x,7) == 0)
fprintf(fileID,'%d',x);
end %end of if
end %end of for
fclose(fileID);