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

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

Related

How to assign each element/column of output to a different variable

In Matlab some functions adapt their output to the number of output variables in the call. For example I can do:
A=[[1 2 3];[4 5 6]];
s=size(A);
And I get
s=[2, 3];
But if I want to handle independently width and height I can do:
[h, w]=size(A);
And I get:
h=2;
w=3;
Now, if I have a function that always output a vector of let's say 3 elements. Is there a way to assign each element to a different variable?
I mean to avoid an scenery like this:
pos=getPosition();
X=pos(1);
Y=pos(2);
Z=pos(3);
I hope I have explained what I mean.
I've had the same problem. Mostly with functions handling coordinates as in your example. My solution was to create the following function:
function varargout = dealOneByOne(vector)
% Assign each column of vector to each variable on the output variables
%
for i=1:size(vector,2)
varargout{i}=vector(:,i);
end
end
Then you can just do
[X,Y,Z]=dealOneByOne(getPosition());
I'm not aware of a simpler way to do it.
Let's define a test function as follows:
function x = test()
x = [1 2 3];
end
Given the function above, this is what I would normally perform in order to split the output array into many distinct variables:
out = num2cell(test());
[a,b,c] = deal(out{:});
A wrapper function can be defined in order to avoid spreading the above assignment into multiple lines:
[a,b,c] = vout_num(test());
function varargout = vout_num(x)
C = num2cell(x);
varargout = C(:).';
end
In your example, the wrapper function would be used as follows:
[X,Y,Z] = vout_num(getPosition());

Looping a Function in Matlab

total newbie here. I'm having problems looping a function that I've created. I'm having some problems copying the code over but I'll give a general idea of it:
function[X]=Test(A,B,C,D)
other parts of the code
.
.
.
X = linsolve(K,L)
end
where K,L are other matrices I derived from the 4 variables A,B,C,D
The problem is whenever I execute the function Test(1,2,3,4), I can only get one answer out. I'm trying to loop this process for one variable, keep the other 3 variables constant.
For example, I want to get answers for A = 1:10, while B = 2, C = 3, D = 4
I've tried the following method and they did not work:
Function[X] = Test(A,B,C,D)
for A = 1:10
other parts of the code...
X=linsolve(K,L)
end
Whenever I keyed in the command Test(1,2,3,4), it only gave me the output of Test(10,2,3,4)
Then I read somewhere that you have to call the function from somewhere else, so I edited the Test function to be Function[X] = Test(B,C,D) and left A out where it can be assigned in another script eg:
global A
for A = 1:10
Test(A,2,3,4)
end
But this gives an error as well, as Test function requires A to be defined. As such I'm a little lost and can't seem to find any information on how can this be done. Would appreciate all the help I can get.
Cheers guys
I think this is what you're looking for:
A=1:10; B=2; C=3; D=4;
%Do pre-allocation for X according to the dimensions of your output
for iter = 1:length(A)
X(:,:,iter)= Test(A(iter),B,C,D);
end
X
where
function [X]=Test(A,B,C,D)
%other parts of the code
X = linsolve(K,L)
end
Try this:
function X = Test(A,B,C,D)
% allocate output (it is faster than changing the size in every loop)
X = {};
% loop for each position in A
for i = 1:numel(A);
%in the other parts you have to use A(i) instead of just A
... other parts of code
%overwrite the value in X at position i
X{i} = linsolve(K,L);
end
end
and run it with Test(1:10,2,3,4)
To answer what went wrong before:
When you loop with 'for A=1:10' you overwrite the A that was passed to the function (so the function will ignore the A that you passed it) and in each loop you overwrite the X calculated in the previous loop (that is why you can only see the answer for A=10).
The second try should work if you have created a file named Test.m with the function X = (A,B,C,D) as the first code in the file. Although the global assignment is unnecessary. In fact I would strongly recommend you not to use global variables as it gets very messy very fast.

MATLAB force function to output n arguments

Is there a way in matlab to force a function to output a certain number of arguments? For example this is what matlab does:
function [a,b,c] = practice
if nargout >=1
a =1;
end
if nargout >=2
b=2;
end
if nargout ==3
c = 3;
end
end
d(1:3) = practice()
% d = [1 1 1]
I would want:
d(1:3) = practice()
% d = [1 2 3]
Can I get this behavior without needing to say
[d(1),d(2),d(3)] = practice()
There is an option to let your function output everything when only a single output argument is used:
function varargout=nargoutdemo(x)
varargout{1}=1;
varargout{2}=2;
varargout{3}=3;
if nargout==1
varargout={[varargout{:}]};
end
end
For non uniform return data, it might be necessary to switch to a cell
If you wish not to change the function, you could use this a little bit more generic code:
out=cell(1,3)
[out{:}]=practice
Please not, that this returns a cell, not an array. That's because array to comma separated list conversion is not directly possible.

Update a M.file variables from command windows in Matlab?

I have a simple but interesting question. i tired hard to google it but my google got upset and giving me the same results...
i wanted to know is it possible to Update a constant variable form workspace command..
A Simple Example:
function y =StupidQuestion
a = 10; % some value
b =[5,6,7;1,2,8]; % some value
y = b*a % some operation
I forget to tell you that we can do it with simulink block by using below command
set_param('obj', 'parameter1', value1, 'parameter2', value2, ...)
i Want to use the assigned value for 3 weeks and without any reason i wants to change my values [a,b] to other but through command windows. any Idea. Waiting for your interesting Reply...................
You can set defaults for the inputs:
function y = foo(a,b)
if nargin < 1 || isempty(a), a = 10; end
if nargin < 2 || isempty(b), b = [5,6,7;1,2,8]; end
y = b*a
end
You can call foo() without inputs (and it will use the defaults for a and b) or supply your own values as: foo(12), foo(12,[10,20]), foo([],[23,23]), etc...
A possible way is to save some variables in an external file. Note that in this case a and b are only in the function workspace (you won't see their values unless you load the contents of test.mat separately). I'm passing the filename in rather than hard-coding it in case you need to switch between multiple settings.
Personally I would prefer to have a human-readable data file, but the concept remains the same (you'd just need some parser function which returned values for a and b given a file).
a = 10; % some value
b =[5,6,7;1,2,8]; % some value
save('test.mat','a','b');
clear a b;
function y = savedvariables(filename)
load(filename);
y = b*a; % some operation
end
y = savedvariables('test.mat');

Matlab UnitTest TestCase with optional plots of results?

While testing objects and functions of a project in Matlab using matlab.unittest.TestCase classes (new to 2013a), sometimes a plot is needed to visualise the actual/expected data.
I have so far used the following method but feel this isn't the best way:
classdef test1 < matlab.unittest.TestCase
properties
var1=3; var2=5; % sample variables
graph_output = 0; % boolean
end
methods(Test)
function testfunction(testCase)
my_result = my_fun(testCase.var1, testCase.var2);
testCase.verifyEqual(my_result,expected_result)
if testCase.graph_output
plot(my_result)
end
end
end
In the command line, I use test_obj=test1 and then test_obj.graph_output=1 before using run(test_obj) to output graphs as well as testing the function.
A better way to do this would be to use a separate method. I have tried this by allocating my_result to the properties list, but after the test completes, matlab seems to re-initialise my_result making the output graph meaningless.
Does anyone know a way round this, or any better way of outputting test results on demand?
Update: This is now much more streamlined in R2017a with the inclusion of FigureDiagnostic and ScreenshotDiagnostic. Check them out before going too far down this path!
Original Answer
You can do this not only for failing conditions but also for passing conditions with a combination of custom diagnostics and the DiagnosticsValidationPlugin. You can do this quickly using a function handle, but if this is something you find you want to do often for many of your tests, consider creating your own subclass of Diagnostic:
classdef PlotDiagnostic < matlab.unittest.diagnostics.Diagnostic
properties
Title
Actual
Expected
end
methods
function diag = PlotDiagnostic(title, actual, expected)
diag.Title = title;
diag.Actual = actual;
diag.Expected = expected;
end
function diagnose(diag)
diag.DiagnosticResult = sprintf('Generating plot with title "%s"', diag.Title);
f = figure('Title', diag.Title);
ax = axes('Parent', f);
plot(ax, 1:numel(diag.Actual), diag.Actual, 'r', 1:numel(diag.Expected), diag.Expected','b');
end
end
end
Then you can have a test that uses this like so:
classdef FooTest < matlab.unittest.TestCase
methods(Test)
function testFails(testCase)
actual = 1:10;
expected = fliplr(actual);
testCase.verifyEqual(actual, expected, PlotDiagnostic('Title1', actual, expected));
end
function testPasses(testCase)
actual = 1:10;
expected = actual;
testCase.verifyEqual(actual, expected, PlotDiagnostic('Title2', actual, expected));
end
end
end
Now once you have those as test diagnostics you will see them in failure conditions. However, you can also see them in passing conditions using the DiagnosticsValidationPlugin, which evaluates diagnostics even in passing conditions to ensure the diagnostic code is bug free (it would be super lame to not catch diagnostic info from a real failure because there was a bug in the diagnostic code that is typically not exercised). This would look like:
>> import matlab.unittest.*;
>> runner = TestRunner.withNoPlugins;
>> runner.addPlugin(matlab.unittest.plugins.DiagnosticsValidationPlugin);
>> suite = TestSuite.fromClass(?FooTest);
>> runner.run(suite)
Note that as of R2014a you can write your own plugin to listen to these passing diagnostics instead of using the DiagnosticsValidationPlugin. Really in this example we are not using this plugin with the intent to validate that the diagnostics are bug free, so it would be better to write a custom plugin with this specific purpose in mind.
Also, in R2014b you can leverage the log method to hook this up to a different dial. If' you'd like you can call:
testCase.log(Verbosity.Detailed, PlotDiagnostic('Title2', actual, expected));
Then you only see the plots when you are using a LoggingPlugin at the "Detailed" verbosity level, for example.
Usually when people are interested in looking at results from a specific test it's because something has gone wrong. This is a good opportunity to use custom diagnostics. Here is one that prints out a link to the MATLAB command window which plots the expected value against the actual value, as well as printing out links which will load the data from the test into the workspace.
classdef test1 < matlab.unittest.TestCase
methods(Test)
function firstTest(testCase)
import matlab.unittest.constraints.IsEqualTo;
% Test should pass!
actualValue = 1:10;
expectedValue = 1:10;
diagnostic = #()myPlotDiagnostic(actualValue, expectedValue);
testCase.verifyThat(actualValue, IsEqualTo(expectedValue), diagnostic);
end
function secondTest(testCase)
import matlab.unittest.constraints.IsEqualTo;
% Test should fail with a diagnostic!
actualValue = [1 2 3 4 12 6 7 8 9 10];
expectedValue = 1:10;
diagnostic = #()myPlotDiagnostic(actualValue, expectedValue);
testCase.verifyThat(actualValue, IsEqualTo(expectedValue), diagnostic);
end
function thirdTest(testCase)
import matlab.unittest.constraints.IsEqualTo;
% Test should also fail with a diagnostic!
actualValue = [1 2 3 4 -12 6 7 8 9 10];
expectedValue = 1:10;
diagnostic = #()myPlotDiagnostic(actualValue, expectedValue);
testCase.verifyThat(actualValue, IsEqualTo(expectedValue), diagnostic);
end
end
end
function myPlotDiagnostic(actualValue, expectedValue)
temporaryFile = tempname;
save(temporaryFile, 'actualValue', 'expectedValue');
fprintf('Plot Data\n', num2str(expectedValue), num2str(actualValue));
fprintf('Load data into workspace\n', temporaryFile);
end
Running this test will result in outputs which contain
Links which will load the actual and expected values into the workspace
Links which when clicked will produce the following graphs:
These will of course only show up though if the test fails, but this is generally the desired behaviour anyway!
N.B. I prefer to use the IsEqualTo syntax so that the tests read (almost) like English. But this is a style decision.