Matlab. The coding languages of engineers. Learn the basics, from variables to more with this supernote. The current chapters are:
All programming languages are either:
Programming languages can be classified as either:
A computing language & interactive environment for algorithm development, data visualisation, data analysis and numerical computation, e.g.
Matlab has a range of potential applications in biomedical engineering, e.g.:
Matlab alternatives include Octave, Freemat & Scilab
Variables can be created by assigning values to them in the command window, e.g.
a = 1
y = 3
c = a+y
d = a^y
e = y/2 - a*4
Inbuilt functions of Matlab can also be used, e.g.
sin(pi/4)
z = tan(a)
Variables can be scalar values or arrays of values:
c = 2;
d = [1 3 4 2 5];
e = [2, 2, 3, 3, 2];
Matlab allows array operations to be performed on each array element separately:
c^3
d+3
d.^3
d.^e
d.*e
Arrays can also be created using the shorthand colon operator:
x = 1:100;
y = 20:5:50;
z = 0:0.1:pi;
Or using the linspace command
x = linspace(1,100,100);
y = linspace(20,50,7);
Individual array elements can be accessed using round brackets:
d = [1 3 4 2 5];
e = [2 2 3 3 2];
d(3)
e(1:3)
It is possible to assign values to the array elements in the same way:
d(3) = 0
f = e(1)
g = [d(1) e(2) d(3) 5 10]
Matlab provides a number of built-in functions specifically for array operations:
max(d)
- maximum value of dmin(d)
- minimum value of dsum(d)
- sum of values of dmean(d)
- mean of values of dstd(d)
- standard deviation of dpt1 = [0 1 1]; pt2 = [1 1 0];
dot(pt1,pt2)
- dot productcross(pt1,pt2)
- cross productMatlab values/variables can take the following data types:
1.234
(single, double)3
(int8, int16, int32, int64)’a’
(char)true
(logical)It is possible to find out the data type of a MatLab variable using the whos command:
a = [1 2 3];
b = ‘x’;
c = false;
whos a b c
There are a number of ways of loading and saving data in Matlab, e.g. dlmwrite writes text files with different delimiters between the array values:
f = [1 2 3 4 9 8 7 6 5];
dlmwrite('test.txt',f,'\t');
The load and save commands can be used to store (parts of) of your workspace for later use:
d = load('test.txt');
e = d / 2;
save('newdata.mat', 'd', 'e');
save('alldata.mat');
clear
load('alldata.mat');
2D plots can be produced using the plot command, e.g.
x = 0:0.1:2*pi;
y = sin(x);
plot(x,y,'-b');
It is possible to add annotations or the graph:
title(‘My Sine Plot);
- Adds a title to graphxlabel('Angle in radians’);
- Adds x-axis labelylabel('Sine’);
- Adds y-axis labelaxis([0 pi 0 1]);
- Defines figure boundariesIt is very easy to define matrices in MatLab using 2D arrays:
a = [1 2; 3 4];
b = [2, 4;
1, 3];
Access matrix elements using round brackets:
a(1,2)
b(1,:)
Assign matrix elements in the same way:
b(2,2) = 3;
a(:,2) = [4; 5];
There are built-in Matlab functions for initialising arrays:
a = zeros(2,2)
- matrix of zerosb = ones(2,2)
- matrix of onesc = eye(2,2)
- identity matrixNote the difference between matrix operations and element-wise operations:
d = b * c
- d is a matrix of onese = b .* c
- e is the identity matrixFor complex series of operations script m-files can be very useful. Just make sure you save your script with the .m extension!
When writing more complex scripts, it is a good idea to comment code. Any text on a line after a %
sign will not be interpreted by MatLab. e.g.
x = [1 2 3]
% comment here
y = x.^2
Scripts do not always work first time, however to help you debug your scripts, Matlab provides two useful tools:
A program can be shown to have a flow of control. Parts of it may be executed and others might not be. Execution order can vary. e.g. it depends on the inputs.
Normal flow of control program statements is sequential, i.e
statement
—> statement
—> statement
With conditional statements, the control flow can change depending on a condition, i.e.
condition 1
—true—>statement a
condition 1
—false—>statement b
if
statementThe if statement is one way in which conditional control flow is implemented in Matlab, e.g.
a = input('Enter a number:');
if (a >= 0)
root = sqrt(a);
disp(['Square root = ' num2str(root)]);
else
disp(['Number is -ve, no square root']);
end
The else statement is optional. However depend on the value of a we can have two different outputs.
Relational | Logical | ||
---|---|---|---|
== |
Equals to | ~ |
NOT |
~= |
Not equals to | && |
AND |
< |
Less than | || |
OR |
> |
Greater than | ||
<= |
Less than or equal to | ||
>= |
Greater than or equal to |
An example:
...
at_risk = false;
if (gender == 'm') && (calories > 2500)
at_risk = true;
end
if (gender == 'f') && (calories > 2000) at_risk = true;
end
...
Highest Precedence | ||
1 | () |
Brackets |
2 | ’ |
Matrix transpose |
2 | .^ |
Element-wise power |
2 | ^ |
Matrix Power |
3 | - + |
Unary plus and minus |
3 | ~ |
Logical not |
4 | .* |
Element-wise multiplication |
4 | ./ |
Element-wise division |
4 | * |
Matrix multiplication |
4 | / |
Matrix division |
5 | + |
Addition |
5 | – |
Subtraction |
6 | : |
Colon Operator |
7 | < |
Less than |
7 | <= |
Less than or equal to |
7 | > |
Greater than |
7 | >= |
Greater than or equal to |
7 | == |
Equal to |
7 | ~= |
Not equal to |
8 | && |
Logical and |
9 | || |
Logical or |
Lowest Precedence |
If we now evaluate a condition using these operator precedence rules. So gender == 'm' && calories > 2500
is equivalent to (gender == 'm') && (calories > 2500)
.
switch
statementCan be used to test a variable against multiple values, rather than using multiple if statements. Here is an example:
switch day
case {1,2,3,4,5}
day_name = 'Weekday';
case {6,7}
day_name = 'Weekend';
otherwise
end
Iteration statements are an alternative way to alter the control flow of a program. They permit a statement (or statements) to be executed multiple times. Two types of iteration statement in Matlab:
for
loopswhile
loopsfor
loopsfor loops execute statement(s) a number of times. However the number of times must be known before the loop starts. e.g.
n = input('Enter number:'); f = 1;
if (n >= 0)
for i = 2:n
f = f * i;
end
disp(['Factorial of ' num2str(n) '=' num2str(f)]);
else
disp(['Cannot compute factorial of -ve number']);
end
while
loopswhile loops also execute statement(s) a number of times. The number of times is determined by the condition, and need not be known in advance. e.g.
i = round(rand(1) * 9) % random integer between 0 and 9 guess = -1;
while (guess ~= i)
guess = input('Guess a number:');
if (guess == i)
disp('Correct!');
else
disp('Wrong, try again ...');
end
end
In general, use:
for
– if you know the number of iterations at the beginning of the loopwhile
– if you don’tOften there are a number of different ways of implementing a program to solve a given problem. One way may be more efficient (i.e. run quicker) than another. Here is an example of a piece of code:
tic
nRands = 1000000;
for i=1:nRands
rand_array(i) = rand(1);
end
toc
The tic ... toc
is an inbuilt function used to time the code lying in-between them. It takes a lot of time to generate an array of 1,000,000 random numbers. A way to improve the efficiency in this case is to allocate an entire array before the for loop starts. Now there is no time-consuming copying of memory blocks:
tic
nRands = 1000000;
rand_array = zeros(1,nRands);
for i=1:nRands
rand_array(i) = rand(1);
end
toc
Jump statements unconditionally transfer control to another part of the program. There are two types of jump statement in Matlab:
break
statementcontinue
statementbreak
statementThe break statement transfers control to after the immediately enclosing for or while loop:
total = 0;
while (true)
n = input('Enter number: ');
if (n < 0)
disp('Finished!');
break;
end
total = total + n;
end
disp(['Total = ' num2str(total)]);
continue
statementThe continue statement transfers control to the next iteration of the immediately enclosing for or while loop:
total = 0;
for i = 1:10
n = input('Enter number: ');
if (n < 0)
disp('Ignoring!');
continue;
end
total = total + n;
end
disp(['Total = ' num2str(total)]);
Note the nesting of control structures in the above example. To preserve program clarity it is often good to avoid excessive nesting.
In mathematics we think of functions like this:
In programming, functions are a little different. In Matlab, a function can:
However all are optional, i.e. it is ok for a function to have no inputs.
Matlab has many ‘built in’ functions, sin
, mean
, sort
etc. We can also write our own functions to perform specific tasks:
function out = add_two(in)
% Usage:
% out = add_two(in)
% in : Argument passed in
% out : Output, the result of adding two to the input.
out = in + 2;
end
In this case code is saved in a file named add_two.m and it is very important that the name of the m-file matches the name of the function. The name must start with a letter. This first letter can only be followed by letters, numbers and underscores. No dashes!
To call our function at the command line. We pass a
as an input argument to the function add_two. The return value is then assigned to b
:
>> a = 5
a =
5
>> b = add_two(a)
b =
7
Matlab has many built in functions, a few more examples include:
fprintf
– Displays a message written by the user and can include variables.rand
– Displays random number(s).numel
– Displays the number of elements in an array.The scope of a variable describes where it can be accessed and used, i.e. where it is ‘visible’. This is useful at the command line or within a function (e.g. when debugging)
However be careful as the same name can be used for different variables if they have different scope. In the following example both places (the command line and in the file) have a variable x
nut they are not in the same scope:
At the command line
>> x = 11;
In the file my_cube.m
function y = my_cube(x)
y = x * x * x;
end
You can check which variables are in current scope as they appear in the workspace window. Or you could use the whos
command.
When you save any sequence of commands in a ‘.m’ file, the file is known as a script. There are many differences between scripts & functions:
Script | Function |
---|---|
No function/end keywords |
Wrapped in function/end |
No arguments in and out | Can have arguments in and out |
To change behaviour: need to edit file | To change behaviour: call with a different argument |
Variables in the workspace are affected | Variables in the workspace are not affected |
Script’s variables are in the same global scope as workspace | Function variables are in the its local scope |
It is possible to have more than one function in a file. The first function must match the name of the file. It is then possible for this function to call another function which is defined later on in the file. e.g.
function scratch()
disp('Call to scratch')
foo()
end
function foo()
disp('Call to foo!!')
end
However in this case, the function foo
can only be called from within scratch.m or from the command line. It is not in scope to be called from inside another script.
It is illegal to start off an m-file as a script and then attempt to finish it by defining a function. Matlab is not a ‘pick-n-mix’ language.
fprintf
in more depthThere are many different ways in which fprintf can be used. Here are a few common examples:
In the following case, %f
interprets the result of x + y
as a floating point number:
fprintf('The sum is %f\n', x + y)
\n
is used to denote a new line after printing:
fprintf( 'low\n' )
%u
is interpreted as an unsigned integer, i.e. in the below case, it denotes the value of total:
fprintf('Sum = %u\n' , total)
fprintf is a very flexible function and can be used in more complex situations. Here it interprets the first argument as a string, due to %s
and the second as an unsigned integer due to %u
:
name = 'Jack';
age = 21;
fprintf('%s is %u years old\n' , name, age)
If code is written so that it explicitly checks for errors. Later on it helps debugging and tracking down causes of errors. And this in turn makes the code more robust.
Matlab has built-in functions to help checking:
warning
: when function can proceed but may not work as expectederror
: when function really cannot proceedBelow is a detailed example of how the error function can be used. The following function expects an array of numbers. If the user gives an empty, we should not return a result:
function [l,m] = compare_to_mean(x)
% usage:
% [l,m] = compare_to_mean(x)
% Input:
% x - A list of numbers
% Outputs:
% l - Number of values in x less than mean
% m - Number of values in x greater than mean
% Check:
if isempty(x)
error('compare_to_mean: %s' , 'Input array empty.');
end
% ... rest of function below
The built in isempty
function checks if the input is valid. If the check fails, the error
function is called. This will cause the function to halt and return. Note, the arguments to error
are treated in the same way as fprintf
.
We can also include a warning function is the example:
% from previous ...
% A warning check:
if ~ isreal(x)
warning('compare_to_mean: %s' , 'Input has complex values');
end
% ... rest of function below
The isreal
function checks that all the input elements are real (i.e. not complex numbers). If the check fails the warning
function will display a message to the operator. However the overall function will continue but may not result to be what the operator expects.
Just below the toolbar, the user interface tells us the Present Working Directory (PWD). We can also tell where we are using the pwd
command. Functions saved in the files in the PWD can be called directly. But if a function file is located elsewhere, we need to include its location in the Path.
The Matlab Path is actually a list of directories, where Matlab searches for files containing functions. We can add our own directories to the list using the addpath
command:
’/path/to/current/directory’
’/some/other/directory’
>> addpath(’/some/other/directory’)
In Windows, we should include the drive letter, e.g. ’C:’
or ’N:’
. For example, if we have files saved in a folder called myMatlabFiles, in ‘My Documents’ on shared drive ’N;’, we should write >> addpath('N:/My Documents/myMatlabFiles’)
in the command line.
Here is an example of a recursive function, it prints a message and then calls itself:
function dontDoThis()
fprintf('No really, ');
fprintf('Don''t do this\n');
dontDoThis()
end
Command Line (0) —> dontDoThis.m
(1) —>dontDoThis.m
(2) —> dontDoThis.m
(2) —> … (Depth of recursion)
However you will get an error:
>> dontDoThis
Maximum recursion limit of 500 reached ... Be aware that exceeding your available stack space can crash MATLAB and/or your computer.
Error in dontDoThis
Such functions need a way to avoid infinite recursion. They need either:
For example if we define a sequence as follows:
Starting at 6 we get the following sequence:
6, 3, 10, 5, 16, 8, 4, 2, 1
It takes 8 steps to reach 1. We want a function to give the number of steps for any stating number. Here is an example of the code which could be used:
function nSteps = recFunc(a)
% base case
if a == 1
nSteps = 0;
return
end
if mod(a,2) == 0
% a is even
nSteps = 1 + recFunc (a / 2);
else
% a is odd
nSteps = 1 + recFunc (3 * a + 1);
end
end
The % base case
is the vital stopping condition. We make a recursive call if we haven’t reached the stopping condition. We add 1 to the steps returned from the recursive call, in order to include the step for the current call.
The editor gives indications about possible errors (red) and warnings (yellow) on the right had side next to the scroll bar. However there are different types of errors, to explain them we use the following example:
clear
a = input( 'Enter a: ' );
b = input( 'Enter b: ' );
c = input( 'Enter c: ' );
r = b * b – 4 * ac;
x1 = (-b+sqrt(r))/(2*a)
x2 = (-b-sqrt(r))/(2*a)
r = b*b - 4 ac
there is no multiplication sign, *
, between 4
and ac
.r = b*b - 4 * ac
the syntax is ok. Even though the editor will not show a syntax error, the code will fail at run time. This is due to the fact that it believes ac
to be a variable and it is not defined. Therefore we still need to add a *
between the ac
in the example to fix this problem.When a function is written, particular kinds of data for the arguments is often expected. We can use the inbuilt error
function when what the input given makes it impossible to proceed. This call to error can be set to give a message to the program-user before exiting and halting the program immediately. For example, a function which estimates the expected weight for a baby whose age is given in months:
function W = expectedWeight(ageInMonths)
% Usage:
% ... usage text goes here ...
if (ageInMonths < 0)
error('Age cannot be negative')
end
% ... rest of function continues below ...
Another inbuilt function known as warning
can be used when it allows the user to proceed with the input but the results may be unreliable. With call to warning
, the message is reported to the user but it does not exit the program but continues. E.g:
function W = expectedWeight(ageInMonths)
% Usage:
% ... usage text goes here ...
if (ageInMonths > 60)
warning('Really a baby??!')
end
% ... rest of function continues below ...
When writing a program to solve a problem or model a system etc. Adopt the following steps for reliable code with fewer errors:
The aim of this method is to always have a working version of the program. Even if it doesn’t yet do everything it is supposed to do. It helps to avoid trying to write everything in one go, and it tests the program repeatedly and often.
Computer memory consists of bits. It is arranged in a line, in groups of eight, known as bytes.
The bits in each byte contain binary values. Set to 1 or 0.
A pattern of bits can be interpreted in different ways. It depends on what data type we assume.
The bit pattern 0100 0001 can be viewed as:
A
Pattern | Decimal | ASCII Character |
---|---|---|
… | … | … |
0011 1100 | 62 | > |
0011 1111 | 63 | ? |
0100 0000 | 64 | @ |
0100 0001 | 65 | A |
0100 0010 | 65 | B |
… | … | … |
If we use a single byte and want to represent unsigned integers (e.g. 0,1,2,3,…), then we can use binary patterns:
0000 0000 | 0 |
0000 0001 | 1 |
0000 0010 | 2 |
0000 0011 | 3 |
… | … |
1111 1101 | 253 |
1111 1110 | 254 |
1111 1111 | 255 |
If we use a single byte and want to represent signed integers (e.g, …,–3,–2,–1,0,1,2,3,…). We need one bit for the sign (+ -). So, fewer bits for the number’s magnitude. i.e. can only represent numbers with a smaller magnitude.
Matlab has two single byte integer data types:
uint8
- “unsigned integer, 8 bits”int8
- “signed integer, 8 bits”The range of these types can be checked using built in functions intmin
& intmax
.
For larger integers, it is possible to use more bytes
>> intmin('uint8')
ans =
0
>> intmax('uint8')
ans =
255
>> intmin('int8')
ans =
-128
>> intmax('int8')
ans =
127
For larger integers, we can use more bytes:
int16 uint16
: 2 bytesint32 uint32
: 4 bytesint64 uint64
: 8 bytesThis means that it is possible to represent a wider range of integers, e.g.
>> intmax('uint16')
ans =
65535
>> intmin('int64')
ans =
-9223372036854775808
These can be represented using scientific notation. This is useful for non-integers and very large/small numbers. e.g.
15! = 130,767,436,800 ≈ 1.3077 × 1012
1 atomic mass ≈ 1.6605 × 10-27kg
We have a mantissa, -7.2101, and an exponent, 7
7.2101 × 107
These can use:
single
: 4 bytes (32 bits)double
: 8 bytes (64 bits)With the allotted bits, we need encode:
Both the Mantissa and Exponent can use:
single
: 4 bytes (32 bits)double
: 8 bytes (64 bits)Both these data types are signed by default. It is possible to check the smallest and largest possible values with built in realmin
and realmax
functions:
>> realmax('double')
ans =
1.7977e+308
>> realmin('double')
ans =
2.2251e-308
In Matlab, specific values of double
can be used to represent:
Nan
)These values can be found with built in functions:
>> isinf(a)
ans = 1
>> isnan(b)
ans = 1
>> a = 2 / 0
a =
Inf
>> b = 0 / 0
b =
NaN
>> c = str2double('blah')
c =
NaN
Can have two values: true
or false
. This is implemented as 1 or 0. A logical value can be created by evaluating a conditional test.
Character | char |
|
Boolean | logical |
|
Numeric | unsigned integers | uint8 uint16 uint32 uint64 |
Numeric | signed integers | int8 int16 int32 int64 |
Numeric | signed floating point | single double |
We can make arrays from basic types:
>> n = 3:-1:0
n =
3 2 1 0
>> r = linspace(0, pi, 3)
r =
0 1.5708 3.1416
2D numeric arrays are known as matrices. Creating matrices allows you to perform a range of linear algebra operations:
c = a*b
d = a+b
e = inv(a)
f = transpose(b)
Arrays from basic types can make character arrays. Character arrays with a single row are described as strings
:
>> s1 = ['c' 'a' 't']
s1 =
cat
>> s2 = 'dog'
s2 =
dog
>> whos s1 s2
Name Size Bytes Class
s1 1x3 6 char
s2 1x3 6 char
Arrays from basic types can make logical arrays:
>> x = 1:3
x = 1 2 3
>> y = 3:-1:1
y = 3 2 1
>> whereEqual = ( x == y )
whereEqual = 0 1 0
>> whos whereEqual
Name Size Bytes Class
whereEqual 1x3 3 logical
It is possible to convert from/to numeric from/to:
However it is not possible to convert from/to logical from/to character
Based on codes used to represent the characters in the look up table:
>> char(66)
ans =
B
>> double('B')
ans =
66
Non-zero numbers get converted to true
. Only zero gets converted to false
:
>> logical(1)
ans =
1 true
>> logical(3.5)
ans =
1 true
>> logical(-12)
ans =
1 true
>> logical(0)
ans =
0 false
Converting the other way, i.e. logical values to numeric:
>> double(true)
ans =
1
>> double(false)
ans =
0
This is where the specific functions, double
, char
& logical
are used to convert between data types.
This is where Matlab converts data automatically without using a dedicated function. e.g. numeric to character:
>> x = 70;
>> str = ['This is number seventy: ' x];
>> disp(str)
This is number seventy: F
This is not what the operator wanted as it converted the number x
based on character codes to F
. In order to get a string representation of the number ’70’
, then the function num2str
should be used.
The same the problem arises with the following example, character to numeric:
>> '3.142' + 1
ans =
52 47 50 53 51
This implicitly converts string (char array) ’3.142’
to an array of 5 numbers based on character codes. It adds one to each. In order to operate on the number 3.142, we need to explicitly convert the string representation:
>> str2double('3.142') + 1
ans =
4.1420
In Chapter 1, we introduced a number of simple functions for reading from/writing to files:
dlmwrite
: write delimiter-separated data to a text file
f = [1 2 3 4 9 8 7 6 5];
dlmwrite('test.txt’,f,’\t’);
load, save
: read/write parts of Matlab workspace in ‘native’ MAT format
d = load('test.txt');
e = d / 2;
save('newdata.mat', 'd', 'e'); save('alldata.mat');
clear load('alldata.mat');
NB: actually all computer files are binary files, but it is common to refer those that use a standard character coding system as text files
Here are the most common functions used for text file input and output:
csvwrite
: write data to comma-separated-value filecsvread
: read data from comma-separated-value filedlmwrite
: write data to delimiter-separated filedlmread
: read data to delimiter-separated fileFor example if the file scanphyslog.txt contains the following respiratory bellows data:
-33 -53 25 -6 0 -1815 0 0 0 0000
-35 -56 24 -9 0 -1815 0 0 0 0000
-37 -59 22 -12 0 -1815 0 0 0 0000
-39 -61 20 -15 0 -1840 0 0 0 0000
-40 -61 18 -18 0 -1840 0 0 0 0000
-40 -60 17 -20 0 -1840 0 0 0 0000
-39 -58 15 -21 0 -1840 0 0 0 0000
-36 -55 15 -21 0 -1840 0 0 0 0000
-32 -50 15 -20 0 -1871 0 0 0 0000
-26 -44 17 -17 0 -1871 0 0 0 0000
-20 -37 19 -13 0 -1871 0 0 0 0000
-11 -30 23 -8 0 -1871 0 0 0 0000
-1 -22 29 -2 0 -1871 0 0 0 0000
It is possible to read in the data and extract the bellows data:
data = dlmread('scanphyslog.txt', ' ');
bellows = data(:,6)
The second argument, ’ ‘
, specifies the delimiter. It returns a 13x10 array know as data. The second line then extracts the 6th column (i.e. the bellows data)
However csvwrite, csvread, dlmwrite, dlmread all have limitations as they only work with text files and the data being read/written must all be numeric.
Most of Matlab’s more flexible file input/output functions require files to be opened before use, and closed afterwards, e.g.
% open file
fid = fopen('test.m','r');
...
% close file
fclose(fid);
fopen
returns a fiel identifier that must be used when referring to the file. The second argument, ’r’
, indicates file access permission:
’r’
: read only’w’
: write only’a’
: appendThe following example is one of a program that finds the length of a program. In the script the file ’count_lines.m’
is open then closed at the end. The script loops until the end of the file; at each line of data it determines whether it is empty/comment, if it is not it adds one to the count. Right at the end of the program the result is displayed.
% open file
fid = fopen(‘count_lines.m','r'); % initialise count
count = 0;
% loop until end of file
while ~feof(fid)
% read line from file
tline = fgetl(fid);
% is it blank or a comment?
if isempty(tline) || strncmp(tline,'%',1)
continue;
end
% count non-blank, non-comment lines
count = count + 1;
end
% print result
fprintf('%d lines\n',count); % close file
fclose(fid);
Here are a few useful functions involved with opening and closing a file:
fopen
, close
- open/close a filefoef
- check for end-of-file conditionfgetl
- read a line from a text filefprintf
- write text (to a file…)If an operator wishes to read the following systolic/diastolic blood pressure data file into a 2D numeric array:
BP data
51 85
88 141
67 95
77 111
68 115
99 171
80 121
A function known as fscanf can be used for this purpose. There are three arguments to fscanf:
fid1
- File identifier’%d %d’
- Format specifier[2 inf]
- Output array sizeHere is an example of a script the operator may wish to right using the fscanf function:
% open file
fid1 = fopen('sys_dia_bp.txt', 'r');
% skip header line
line = fgetl(fid1);
% read systolic/diastolic b.p.
data = fscanf(fid1, '%d %d', [2 inf])
% close file
fclose(fid1);
There are many different format specifiers:
Specifier | Field Type |
---|---|
%d |
Signed decimal integer |
%u |
Unsigned decimal integer |
%f |
Floating point number |
%c |
Character |
%s |
String (i.e. sequence of characters) |
fscanf
exampleIf the operator is presented with strings accompanying the data in his file, he needs to separate the information. e.g.
BP data
Sys 51 Dia 85
Sys 88 Dia 141
Sys 67 Dia 95
Sys 77 Dia 111
Sys 68 Dia 115
Sys 99 Dia 171
Sys 80 Dia 121
In his script, when using the fscanf function, if the operator includes the *
symbol before after %
in the format specifier then it tells Matlab to read the string but not include it in the output array. e.g.
% open file
fid = fopen('test.txt');
% skip header line
line = fgetl(fid);
% read systolic/diastolic blood pressure
data = fscanf(fid, '%*s %d %*s %d', ... [2 inf])
% close file
fclose(fid)
Function | File Type | Operation | Open/Close? |
---|---|---|---|
load |
MAT | Read Matlab variables | N |
save |
MAT | Write Matlab variables | N |
csvread |
Text | Read comma separated value numeric data from file into 1D or 2D array | N |
csvwrite |
Text | Write 1D/2D array of numeric data to file in comma separated value format | N |
dlmread |
Text | Read delimiter separated value numeric data from file into 1D/2D array | N |
dlmwrite |
Text | Write 1D/2D array of numeric data to file in delimiter separated value format | N |
fscanf |
Text | Read dat of single type from file into 1D or 2D array | Y |
fgetl |
Text | Read line of text into a string variable | Y |
feof |
Text | Checks for end-of-line condition | Y |
The rest of this chapter will be completed soon
As programs tackle larger and more complex problems, they cannot normally be easily implemented by writing one big script. It needs to be broken down into simpler modules/fucnctions.
Program design refers to the process of:
There are two different methodologies to software design:
This is most commonly applied in procedural programming. It is also known as stepwise refinement. The basic idea is to:
A good example of this is when designing a perfect number program…
The rest of this chapter will be completed soon
In the early chapters, we have touched on how the plot command can be used to generate simple visualisations and how we can then annotate these plots use functions such as title
& xlabel
.
Sometimes it can be useful to visualise multiple plots at once…
x = 0:0.1:2*pi;
y = sin(x);
y2 = cos(x);
plot(x,y,'-b', x,y2,'--r');
legend('Sine','Cosine');
x = 0:0.1:2*pi;
y = sin(x);
y2 = cos(x);
figure; hold on;
plot(x,y,'-b');
plot(x,y2,'--r');
title('Sine and cosine curves');
legend('Sine', 'Cosine');
x = 0:0.1:2*pi;
y = sin(x);
y2 = cos(x);
figure;
plot(x,y);
title('Sine curve');
figure;
plot(x,y2);
title('Cosine curve');
x = 0:0.1:2*pi;
y = sin(x);
y2 = cos(x);
subplot(2,1,1);
plot(x,y);
title('Sine curve');
subplot(2,1,2);
plot(x,y2);
title('Cosine curve');
figure;
[AX H1 H2] = plotyy(x,y1,x,y2);
title('Exponentially decaying oscillations'); xlabel('Time');
set(get(AX(1), 'Ylabel'), 'String', 'Low frequency oscillation');
set(get(AX(2), 'Ylabel'), 'String', 'High frequency oscillation');
To visualise multiple datasets on the same figure:
plot
hold on
and multiple plot commandssubplot
plotyy
if different y-scales requiredTo visualise multiple datasets of different figures:
figure
command to create multiple figuresMultivariate data is data that has more than 1 value per ‘individual’, e.g.
For data with 3 values per ‘individual’ we can use the plot3
function, e.g.
% the z-coordinate of the helix
t = 0:0.05:10*pi; % 5 times round
% x-coordinate of the helix
st = sin(t);
% y-coordinate of the helix
ct = cos(t);
% 3-D plot
figure;
plot3(st, ct, t, '.b') title('Helix');
xlabel('X'), ylabel('Y'), zlabel('Z');
Whereas plot3 is used for visualising multivariate data as lines/points etc., the mesh
and surf
commands can be used to visualise surfaces. e.g.
% create grid of x/y values
[X,Y] = meshgrid(-8:.5:8, -8:.5:8);
% define sinc function
R = sqrt(X.^2 + Y.^2) + eps;
Z = sin(R)./R;
% mesh plot
mesh(X,Y,Z)
title('Sinc function');
xlabel('X');
ylabel('Y');
zlabel('Z');
Matlab provides a number of commands for reading/writing/visualising images, e.g.
% read image
im = imread('fluoro.tif');
% display image
imshow(im);
% modify image
im(100:120,100:120) = 0;
% save image (saves 'im' array)
imwrite(im, 'fluoro_imwrite.tif');
% save image (saves figure as displayed)
saveas(gcf, 'fluoro_saveas.tif');
imread
reads an image from a file into a 2D array.imshow
displays the imageimwrite
writes the array to a filesaveas
saves the current figure (gcf) to a fileComputer programs (code) can be:
Sometimes this is important, however often it is not. Typically, readability is more important.
Can be assessed directly by timing how long code takes to run. Time will vary even on the same machine, as it depends on the hardware and the load on the machine. The inbuilt tic...toc
function is used to measure this, and it prints the time taken of the lines of code in-between the function. e.g.
function sumOfIntegers(N)
% ...
tic
for j = 1:N
total = total + a(j);
end
toc
% ...
>> sumOfIntegers(1000000)
Elapsed time is 0.014182 seconds.
...
The rest of this chapter will be completed soon
Increasingly, imaging data is a vital resource for healthcare professionals, e.g. MR, CT, Ultrasound, PET. Therefore, knowing how to process and manipulate medical images is a vital skill for biomedical engineers.
The rest of this chapter will be completed soon