MATLAB: Copying Global variable for all Workers - matlab

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.

Related

How to access and modify values of variables in matlab workspace?

There are few variables in my matlab workspace, lets say a and b.
eg: a = 1:5;
b = 1:10;
I used who to get their names.
like listVariables = who;
now listVariables has the variable names a and b, but i dont know how to access their values so that I can do some mathematical operations on them.
It looks like evalin is what your are searching for:
a_val = evalin('base', listVariables{1});
b_val = evalin('base', listVariables{2});
The advantage of evalin is that it can be executed from a function (out of the scope of the workspace).
Example:
In workspace:
a = 1:5; b = 1:10;
Content of my_fun.m:
function my_fun()
listVariables = evalin('base', 'who');
a_val = evalin('base', listVariables{1});
b_val = evalin('base', listVariables{2});
display(a_val);
display(b_val);
Result of my_fun() execution:
a_val =
1 2 3 4 5
b_val =
1 2 3 4 5 6 7 8 9 10
Note: there are cases in which evalin is useful, but it's not a good coding practice.

Can we configure MATLAB let variable have minium local scope?

Can we configure MATLAB let variable have minium local scope?
I want matlab something similiar like C below.
% after some configure ...
for i=1:1:100
a=i*i
end
% here we can not using 'a' any more for it have local scope in for loop.
Why I want it becase the scope in whole script sometimes leds to bug hard to find.
For example:
% get accumulate of b via 100 times of x_0
b=0;
for i=1:1:100
x0=100
b=b+x0
end
% get accumulate of a via 100 times of x_0
a=0
for i=1:1:100
x_0=200
a=a+x0 %mistype x_0 to x0, and hard to find
end
Thanks advance.
I don't think there is any way to force a local scope in a script/loop. However, you can create a function, in a separate file or in the same file. Each function will have it's own local scope. So for your example you can create a file myScript.m with the following:
% get accumulate of b via 100 times of x_0
accum_b(100)
% get accumulate of a via 100 times of x_0
accum_a(200)
function a = accum_a(x0)
a = 0;
for k = 1:100
a = a + x0;
end
end
function b = accum_b(x0)
b = 0;
for k = 1:100
b = b + x0;
end
end
In this particular example, you can of course call the accum_a function twice, with different x0 inputs. But each function you define in a file will have it's own local scope, and will thus result in an error when mistyping x_0/x0.

Continue ‘for’ loop with the existing variables in Matlab

I have a Matlab script including a for loop which loos like the following:
for k = 1:10
c = myfun(k,a,b);
result{k} = c;
end
Right now, the problem is that during the for loop, sometimes myfun() may have errors and stop. After fixing the error in myfun(), how can I continue to run with the existing value of variables? The reason is that myfun() will take a very long time to get the result and the previous results are right.
For example, if a error happens when k == 4, then I save all the variables in the current workspace. I set a breakpoint at c = myfun(k,a,b); and restore the saved variables, but I find that in the next loop, k will be 2 instead of 5 as I want. Matlab is not allowed to modify the value of k during the for loop I think. I have tested this for a few times.
How can I continue the for loop with some existing data?
You cannot change your for loop iterator programmatically inside of the loop.
For example:
for ii = 1:3
disp(ii)
ii = 3;
end
Prints:
1
2
3
If you're going to be modifying code based on errors received, dbstop if error is not going to be beneficial because it will not reflect changes in your code until the debugger is exited and your code executed again (unless you execute manually in the debugger). If you're not modifying code you could potentially use a try/except clause to catch fixable issues.
If you're loading data for a later index and then restarting, you can change where your for loop begins, or use a while loop (if appropriate).
For example:
% Load data here
for ii = 3:3
disp(ii)
end
Prints 3.
Where the while interpretation would be:
% Load data here
ii = 3
while ii <= 3
disp(ii)
ii = ii + 1;
end
For the same result.
On solution can be first catch the exception likes the following and pass from them:
bug = [];
for k = 1:10
try
c = myfun(k,a,b);
result{k} = c;
catch
warning('some bug for the following values:');
display([k a b]);
bug = [bug; k a b];
result{k} = NaN;
end
end
Then iterate over bug to compute missing information after debugging. This solution works when your algorithm is not dependent on the previous value of the result (or is not recursive).

Matlab functionality similar to python's __name__=='__main__'

I am looking for Matlab functionality to differentiate when script is run directly or from another script.
I build a script where I declare data to work on and I use this on other scripts and functions. When I run this script directly I would like to plot these data. When I call this script from another script I don't want to have all those plots.
In python I can build a function for plottings and call this function only when __name__=='__main__' I can't find how to do that in Matlab.
As example:
data.m
a = [1 2 3 4 5]
b = sin(a)
% plot only if run directly
figure
plot(a,b)
analysis.m
data
c = a.^2
figure
plot(c)
When I run analysis.m I want to have only plot(c) but not any other.
You can use ´dbstack´ [1] to see the function calls.
To complement #tashuhka answer (i.e using dbstack), and depending if you want to keep variables in the global scope, another solution is to turn your script into function and pass optional parameter to 'analysis.m'.
function [] = foo(doDebugPlot)
%[
% Check params
if (nargin < 1), doDebugPlot = true; end
% Code
...
% Debug
if (~doDebugPlot), return; end
plot(lala);
plot(tutut);
%]
I don't know if this is possible in MATLAB. A workaround would be to use an if together with exist, like this:
analysis.m
run_data = 1;
data
c = a.^2
figure
plot(c)
data.m
a = [1 2 3 4 5]
b = sin(a)
% plot only if run directly
if ~exist('run_data','var')
figure
plot(a,b)
end

Modify script from another script

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