This is a note taken from MATLAB online self-paced course.
Utilizing Development Tools
Directory reports
- Commonly used folder reports in MATLAB
- Code Analyzer report: displays code analyzer findings for each code file
- Dependency report: shows the function dependencies of the code files in the current folder
- Help report: provides each code file’s help text in a single report
- TODO/FIXME report: lists the instances of “TODO”, “FIXME”, or other custom text that exist in comments
- To run these reports, navigate to the desired folder in MATLAB and then use the
Current Folder Actions
menu.
Code Analyzer
- 出现红色波浪线(即warning)时,右键单击,就有显示的帮助fix的选项
- 如果没有fix,并且你觉得没有问题时,就可以右键选择”Suppress XXX”, 这时MATLAB会帮助你在后面加上一个注释
#Ok<AGROW>
来表示没有问题
MATLAB debugger
- use breakpoint
- run MATLAB with
Pause on Errors
can help relief the work to find where is the bug.
Execution time measurements
tic
andtoc
functions can help measure the execution time of MATLAB code- Because tic and toc measure clock time, your computer’s background tasks can cause the timing measurements to vary slightly. Therefore, tic and toc may give different results for consecutive timings of the same code.
- Average several running times is a good idea:
1
2
3
4
5
6tic; x = rand(1000); t(1) = toc;
tic; x = rand(1000); t(2) = toc;
tic; x = rand(1000); t(3) = toc;
mean(t)
ans =
0.0305
Code profiler
- To know which parts of the code take the most time.
- Click
Run and Time
opensMATLAB Profiler
window - Enter a line of code in the edit box and then press Enter or click the
Start Profiling
button. - Note: The profiler report does not provide information on each individual call to a function, but rather only information on the conglomeration of all calls to a function.
Createing Robust Application
Custom Warnings and Errors
- use
warning
anderror
to customize - Warnings and errors both contain two components: an identifier and a displayed message
- Identifier:
- Hidden from the user
- At least contains two components and separated by ‘:’
- First component is typically the name of the application
- Second component identifies the condition for the error or the warning
- Error or warning message
- is displayed to the user
- Errors are displayed in red and warnings in orange
- e.g.
warning('MyProject:ValueOutOfRange','The value must be between 1 and 10.')
Validating Function Inputs
- MATLAB provides several functions for validating the attributes of a variable.
- Validating Multiple Attributes:
validateattributes(name,class,attributes)
name
: the variable nameclass
: should be a cell array containing strings, e.g: {‘double’}, {‘cell’}, {‘numeric’}, etc.attributes
: should be a cell array containing the list of attributes and their expected values, e.g.: {‘vector’}, {‘nonempty’}, {‘scalar’,’>’,10}, etc.- e.g.: checks that the data passed into the variable r is a numeric scalar greater than 0:
validateattributes('r',{'numeric'},{'scalar','>=',0})
You can also provide additional flexibility to the user by converting the input provided by the user into something that is acceptable to the program.
- e.g. calling the following by
int = calculateInterest(500,2,'2%')
, and returnint = 20
1
2
3
4
5function interest = calculateInterest(p,n,r)
if ischar(r)
r = str2num(r(1:end-1));
end
interest = p*n*r/100;
- e.g. calling the following by
numel
can be used to check the number of elements in a array
Setting Default Input Values
- Missing input: use function
nargin
to check if all the inputs were provided in the function callnargin
returns the number of inputs that were passed
- Empty Input:
- use an empty array
[]
to skip specifying some inputs - usie function
isempty
to check if the input is given. If it is empty, we can assign a default value.
- use an empty array
The program flow within the function goes as follows now:
- Are all inputs provided?(nargin) No -> Set default values
- Is any input empty?(isempty) No -> Set default values
Creating Flexible Interfaces
- use the property name-value pairs in the function syntax to allows the user to specify only a subset of the line attributes in any order.
- Every input argument in the function call is mapped to a single variable in the function definition. However, you can map multiple input arguments to a single input variable
varargin
in the function definition. - e.g.
function analyzeAndPlot(x,y,varargin)
can be called asanalyzeAndPlot(time,position,'LineWidth',3,'Color','r')
varargin
is a cell array. In the above example, starting with the third input, each input is assigned to a separate cell of varargin.- The contents of varargin can be passed to other MATLAB functions using like
varargin{:}
varargin
is the last input in the function declaration.
Try-Catch: Unexpected Errors
- The MException Object:
- Error information in MATLAB is stored in a specialized datatype called an MException object.
- can access the MException object for the last error that occurred using the command:
MException.last
The try-catch Construct:
This special programming construct attempts to run the code within the try block. If an error condition occurs, then the execution is interrupted and switched immediately into the catch block.
1
2
3
4
5
6try
% Attempt code
catch mexc
% Backup case – something went wrong
% An MException object called mexc now exists
endYou can provide the name of a variable after the keyword catch (
mexc
in the above example).- If an error is generated in the try block the program can then proceed in one of the following ways in the catch block:
- Try to recover from the error and continue execution.
- Provide a customized error message and halt the execution.
Review of Data Type
whos
: show variables in the workspace and compare their properties.
Table:
- Create a table:
- You can use the table function with the workspace variables as inputs to create a table.
tableName = table(variable1,variable2,variable3,'VariableNames',{'A','B','C'})
- Combine tables:
tableC = [tableA tableB]
- Extracting portions of a table:
- by using column or row number:
tableC = tableA(:,1:2)
- by using variable name in single quotes:
tableC = tableA(:,'FirstVariableName'
ortableC = tableA(:,{'Var1','Var5'})
- mixied indexing:
tableC = tableA([1 3 5],{'Var1','Var5'})
- by using column or row number:
- Extracting Data from a Table
- dot notation:
data = tableName.VariableName
- Add new variable to a table:
table.NewVariable = [5 27 14]'
- Curly Braces:
na1 = patientData{:,{'Name','Age'}}
orpatientData.Name{3} = 'NewName'
(可直接赋值:patientData{[1 4],'HeartRate'} = [80 ; 75]
)
- dot notation:
- use
tablename.Properties.VariableNames
to get the variabe names in a table or index into the VariableNames field to change a variable name:myTable.Properties.VariableNames{2} = 'NewName'
Cell Array
- using parentheses, returns a subset cell array:
currencies(1)
->ans={'Euro'}
(提取出来的还是cell) - using curly braces will return a string:
currencies{1}
->ans='Euro'
(提取出来的 cell 本身的类型,即自身的内容) - using curly braces can also replace or add a content:
currencies{1,3} = 'Yen'
- remove an element from an array, use parentheses and set the result to an empty array,
ezone(2) = [];
Structures
- Structures can contain data of dissimilar types and sizes in one variable. Use dot notation to add a field to a structure.
Function Handles
- You can use a function handle to store a command as a variable, which can then be passed as an input to a function.
- construct a function handle by preceding the function name with an @ sign:
h = @sin
- call the function handle as the same way to call the function directly:
h(0)
- For functions requires an input, give the function handle (variable) as an input:
integral(h,0,pi)
,integral(@log,1,2)
Anonymous Functions
- use anonymous functions to create simple functions without creating a code file. That is to say, create a function directly in command line with only input variables.
- syntax:
variableName = @(arg1,...) functionDefinition
, e.g.f = @(x,y) sin(x) + y;
- variableName is the Function Handle
- Call the function just need to give the input into the handle:
f(pi/6,0.5)
Structing Data
Structuring Data Considerations
- Data that contains values from a finite set of categories, may be converted to categorical data using the
categorical
function:gender = {'M' 'M' 'F' 'M' 'F' 'F'}; gender = categorical(gender);
- use
cat
to concatenate the output:allSums = cat(1,groupSum{:})
Extracting multiple elements
Applying scalar functions to data
use
cellfun
function to find the group attributes of each cell:cellfun
function applies the specified function to each element of the cell.- the specified function is called once per cell element.
- The specified function is typically a function which accepts a single input and produces a single output. e.g.
1
2
3
4groups =
[3x1 double] [2x1 double] [4x1 double]
cellfunc(@mean, groups)
ans = 3.03 4.30 5.05
use
structfun
to apply the same to a structure, this returns a scalar for each cell1
2
3
4
5
6groups =
group1: [3x1 double]
group2: [2x1 double]
group3: [4x1 double]
structfun(@mean,groups)
ans = 3.03 4.30 5.05Nonscalar output
- You may attempt to use
cellfun
or structfun with functions that return nonscalar outputs, such as sort, return an array. To handle this situation, you can specify that the outputs will be different sizes using the
UniformOutput
property. This returns a nonscalar for each cell. e.g.1
2
3
4
5groups =
[3x1 double] [2x1 double] [4x1 double]
cellfun(@sort,groups,'UniformOutput',false)
ans =
[3x1 double] [2x1 double] [4x1 double]can also use anonymous functions as inputs to
cellfun
:cellfun( @(x) mean(x.price), c)
- You may attempt to use
Converting data types
num2cell
: converts an m-by-n numeric matrix into an m-by-n cell array, where each cell contains a scalar valuemat2cell
: converts a numeric matrix into a cell array where the cells contain matrices of various sizes.- the second input indicates how to subdivide the rows
- the third input indicates how to subdivide the columns
- e.g.
c = mat2cell(r,[2,4],[2,1])
means to convert the matrix r to four matrix cell, each cell has the matrix of dimension: 2x2, 2x1, 4x2, 4x1
cell2struct
: converts a cell array into a structure.- e.g. 4-by-2 cell array
c
is converted into a 2 element structure,s
, with 4 fields:s = cell2struct(c,{'fA','fB','fC','fD'},1)
- first input: the cell array
- second input: a cell of strings containing the field names
- third input: the dimension on which the fields are named. (i.e. row or column)
- e.g. 4-by-2 cell array
cell2table
: converts a cell array into a table- character array:
cellstr
converts a list of strings to a cell array with the trailing spaces removed.
Structing Code
Private Functions
- To prevent your application’s internal functions from being accessible outside the application, you can place them in a folder named private
- Functions in a private folder can only be called by
- Functions within the parent folder
- Other functions within the private folder
- private functions can call any other functions on the MATLAB path.
- private folders cannot be added to the MATLAB path. Therefore, functions within them generally cannot be called from the command line unless the MATLAB current folder is the private folder itself.
Local Functions
- To create local functions, place them below the primary function in the same code file
- When using local functions
- The primary function can call the local functions
- The local functions can call other local functions and the primary function
- External code (outside of the code file) can call the primary function, but not the local functions
- As with functions in separate files, local functions have their own workspaces
- When creating local functions, you may or may not choose to use the
end
keyword for each function. However, whichever you choose, you must stay consistent. Some local functions haveend
while others don’t is invalid in MATLAB
Change the Function Interface with Anonymous Functions
- One way to modify a function’s interface (without modifying the function itself) is to use a wrapper function.
Functions with multiple inputs may not be used directly with other functions like
fzero
,ode45
, using anonymous functions can help this:1
2
3
4
5
6
7
8function y = myquad(x,a,b,c)
y = a*x^2 + b*x + c;
a = 1; b = 5; c = -10;
f = @(x) myquad(x,a,b,c)
fzero(f,3)And the input variables can be the variables in the workspace.
Performance and Memory
Datatypes and Memory
- can determine the memory used by a variable by choosing to display the
'Bytes'
column in MATLAB workspace. - Container variables (tables, cell arrays, and structure arrays) require overhead in addition to the data they store.
- This additional memory is used to store information about the contents of the variable.
- The amount of the overhead depends on the size of the variable.
- Each
cell
of a cell array requires memory overhead. - A
table
requires minimal overhead for each variable and for storing table properties. - A
structure
requires 64 bytes of overhead for each field name. If a structure array has more than one element, each element will require additional overhead.
- Special Variable Types: MATLAB has datatypes that are designed to be used with data having specific characteristics. These datatypes can significantly reduce the memory consumption.
Categorical arrays
can be used to store a list of text labels or strings containing many repeated entries.- The memory saved increases as the size of the list and the number of the repeated entries increase.
Datetime arrays
can be used to store a list of dates. They also provide memory saving over a cell array storing individual date strings.
Preallocation
- Preallocating Numeric Arrays:
- can use the functions
zeros
andones
to preallocate numeric arrays - another way to preallocate an array is to assign a value to the last element of the array.
- can use the functions
- Preallocating Cells and Structures
:- benefit when a for loop used, since frequently change the size will consume lots of time
- Preallocating a cell array or a structure array assigns space for the containers themselves, not the contents
- This means that preallocation of the container variables is most beneficial when the container array itself is large, regardless of the size of the contents of the individual containers.
- using
cell
to preallocate a cell array:C = cell(1,4)
- preallocate a structure array, start by defining the last element of the array. MATLAB will automatically replicate the field names to all of the preceding elements in the array.
S(5) = struct('field1',6,'field2',7)
Vectorization
- a subset of vectorized functions in MATLAB:
diff
,prod
,cumprod
,cumsum
,union
,setdiff
,setxor
etc.
Binary Singleton Expansion (bsxfun)
- Binary: the function should accept two inputs
- Scalar: the function should return a scalar output
1
2
3
4
5
6
7x = [4;5;6]
y = [1 2 3; 4 5 6; 7 8 9];
bsxfun(@gt,x,y)
ans =
1 1 1
1 0 0
0 0 0
Memory Usage
- use the
memory
command to display information about the memory - or with output structures:
[user,sys] = memory
- The output structures have the following information:
- Total System Memory(sys.SystemMemory.Available): Physical RAM available + Page File (or swap) available.
- MATLAB Process Virtual Memory(sys.VirtualAddressSpace): Total and available memory associated with the whole MATLAB process. It is limited by processor architecture and operating system.
- MATLAB Workspace(user.MemAvailableAllArrays) and Largest block(user.MaxPossibleArrayBytes): The effective workspace available for data is the MATLAB process virtual address space minus system DLLs, Java™ (JVM), MATLAB.exe and DLLs. The largest block (for numerical arrays) is affected by fragmentation, third-party DLLs , and other running processes.
Copy-on-Write Behavior
- also named lazy-copying, ensures that no additional memory is assigned to an input variable until it is modified within the function.
In-Place Optimizations
- declare and call a function using the same variable to define the input and output arguments:
x=myFun(x)
Nested Functions
- a nested function is also used to organize several functions in a single function file and it often acts as a helper function to the primary function.
- However, nested functions exihibit one additional feature: They allow functions in the file to share workspace variables.
- To nest a function inside another function, the extents of the functions must be marked explicitly by using the keywords function and end.
When to use a nested function?
- Sharing large data: Auxiliary functions that are intended to modify the data of the parent function can be written as nested functions.
In the following example, even though
x
is not explicitly passed to the nested functionmovingAverage
, the nested function can access and modifyx
from the workspace of the primary functionanalyzeData
:1
2
3
4
5
6
7
8function y = analyzeData(x)
movingAverage(3);
...
function movingAverage(n)
window = ones(1,n)/n;
x = conv(x,window);
end
endUsing a function which requires specific function signature: Some functions in MATLAB, such as fzero, require you to pass handles to your own functions as inputs.
Verifying Application Behavior
What Is a Test?
- A test allows you to verify that your code works correctly by testing specific inputs and validating that expected values have been created.
- A simple test should:
- Set up the circumstances under which you want to test the application.
- Call the application.
- Define the expected value.
- Compare the actual and expected behaviors.
Test Response
- A formal testing framework should produce either no response, to indicate that the test was passed, or an error, to indicate failure.
assert
function takes a logical input (or an expression that evaluates to a logical result), and generates an error only if the input is false.1
2
3
4>> assert(true)
# (No response)
>> assert(false)
Assertion failed.
Writing and Running a Test Script
- A test script is simply a MATLAB script that is divided into sections and uses the assert function.
- Code sections allow you to compile multiple tests into a single file. The section header describes the test. Use
%% Test XXX
to seperate each section. - Each section of a test script maintains its own workspace. Thus, in each section, you must define all needed variables.
- to run each and every section of a test script, use the
runtests
function:result = runtests('myTests');
- If run the test script as a regular script, any failed tests will produce an error, halting execution. Thus, the remaining tests will not be performed.
- Whereas, the runtests function will move to the next section of the script after an error is encountered so that all the tests run.
- Output variable of
runtests
is a specialized MATLAB object designed to hold test result information.
Avoiding Bugs in Comparisons
- Numerical Precision: use a tolerance value for equality comparisons:
abs(x-y) < 1e-6
Writing Test Functions
Creating a Test Function: A test function follows a specific template:
- note: the test local function name should be ended with
Test
1
2
3
4
5
6
7
8
9
10
11function test = mainFunctionName
test = functiontests(localfunctions);
end
function testName1(testcase)
% code for test 1
end
function testName2(testcase)
% code for test 2
end
- note: the test local function name should be ended with
For each test:
- Create a local function.
- Name each test function starting or ending with the word “test.”
- Pass a single input variable.
Verifying Behavior
- to verify that an application behaves in a certain way, such as generating an error or not generating warnings under specific conditions
- Verification functions:
verifyClass
,verifyError
,verifyWarningFree
, etc. - The local test functions have a single input, named
testcase
in the example below. Your test code should use it as the first input to the verification function.1
2
3
4
5function posRootTest(testcase)
x = linspace(0,pi);
y = sqrt(x);
verifyTrue(testcase,isreal(y))
end
Passing Commands as Inputs
1
2
3
4
5function testStringInput(testcase)
errorMessage = 'MATLAB:UndefinedFunction';
cmd = @()sqrt('ZureyBug');
verifyError(testcase,cmd,errorMessage)
end
Adding Pre- and Post-Test Tasks
- It can be useful to define tasks that should be performed immediately before and after running the actual tests defined in your test code. e.g., if you keep the test code and the application in separate locations, the location of the application code can be added to the MATLAB path for the tests to successfully run.
you can add pre- and post-test tasks to your testing function by adding functions with the special names
setupOnce
andteardownOnce
which have the same signature as the other test functions.1
2
3
4
5
6
7
8
9
10
11
12
13function setupOnce(testCase)
% save the name of the application folder you will add
% to the TestData structure
testCase.TestData.appDir = fullfile('C:','class','work','ApplicationDirectory');
% add the application folder to the path for testing
addpath(testCase.TestData.appDir)
end
function teardownOnce(testCase)
% removes the added path
rmpath(testCase.TestData.appDir)
endIn the above example, the test code and the application code are in separate locations. You will use the application folder in the teardown function. So, rather than redefining it, you can save it in the testCase variable to the TestData property. This property is a structure variable to which you can add fields as you desire. Any fields that are added to this variable are accessible by all functions in the test function file.
- remove the directory from the path in the teardownOnce function. See that the variable you previously defined, appDir, is accessible through testCase.TestData. Note that the structure TestData is named automatically, whereas you can name the function input, testCase in this example, whatever you want.
Creating a Toolbox
Creating a Toolbox
- Open the Package Toolbox dialog: Home - Add-Ons - Package ToolBox
- Specify the folder where your application is stored: need to ensure that all the required code files for the application are on the MATLAB path prior to specifying the folder.
- Fill in toolbox information: like author name, company
- Package the toolbox:
- will create a
.mltbx
file that contains all the dependencies and path information needed for you to share the application. - a
.prj
file is also created. This saves the project information that you just entered in the Packager window. This is useful if you later need to repackage your application after making changes to it.
- will create a
Installing a Toolbox
- by double-clicking the
.mltbx
file, this will start the installation process, which adds the files to the local installation of MATLAB - The files are added to the MATLAB Add-Ons folder, and the proper folders are added to the path.
- The location of the MATLAB Add-Ons folder is set in the preferences
- to uninstall a toolbox, open the Add-On Manager
Including Custom Documentation (manual) in the Toolbox
- To add documentation, first create an
info.xml
file at the root level of the toolbox folder. Use a standard template (which can be found in the documentation) to create the initial file. - modify your toolbox’s name and specify the folder where you will store the documentation. In
<name>
and<help_location>
part in the xml file - Create the
doc
folder at the root level of your toolbox, thus matching where you specified it in info.xml. - Create a
helptoc.xml
file in the doc folder. Again, use a template found in the documentation as a starting point. - Specify the content structure of the documentation. This defines the pages that are listed in your documentation’s content tree (typically shown on the left side of the documentation).
- Specify the content structure of your documentation. This defines the pages that are listed in your documentation’s content tree (typically shown on the left side of the documentation).
- In the
doc
folder, create the HTML files that you specified in the helptoc.xml file. Note that you can use any tool you’d like to generate the HTML, such as hand-writing it or even using the MATLAB publish features. - Then, the document is created
1
2
3
4
5
6
7
8
9
10
11
12# template info.xml
<productinfo
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="optional">
<?xml-stylesheet type="text/xsl" href="optional"?>
<matlabrelease>2014b</matlabrelease>
<name>My Toolbox</name>
<type>toolbox</type>
<icon></icon>
<help_location>doc</help_location>
<help_contents_icon>$toolbox/matlab/icons/bookicon.gif</help_contents_icon>
</productinfo>
1 | # template helpdoc.xml |