SCROLL DOWN 

1
Getting Started

 OPEN STANDALONE 

Programming languages

All programming languages are either:

  1. Interpreted: Code translated into machine-readable instructions as the program is run, by the interpreter. e.g. Perl, Python, Javascript, Matlab
  2. Compiled: This involves two steps, first compilation converts code into machine-readable instructions; execution then runs these instructions. e.g. C, C++, Java, Matlab

Three types of programming language

Programming languages can be classified as either:

  1. Procedural: Programs consist of sequence of instructions that operate on data. e.g. C, Fortran, Perl, Matlab
  2. Object-orientated: Programs consist of interacting objects containing data and operations. e.g. C++, Java, Matlab
  3. Declarative: programs consist of statements about the problem or how it can be solved. e.g. Prolog, ML

What is Matlab?

A computing language & interactive environment for algorithm development, data visualisation, data analysis and numerical computation, e.g.

  • Visualise data
  • Perform mathematical computations
  • Write computer programs

Matlab has a range of potential applications in biomedical engineering, e.g.:

  • Image Reconstruction
  • Biophysical Modelling

Matlab alternatives include Octave, Freemat & Scilab

The Matlab environment

Variables and functions

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)

Arrays

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
Creating Arrays

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);
Accessing Arrays

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]
Built in array functions

Matlab provides a number of built-in functions specifically for array operations:

  • max(d) - maximum value of d
  • min(d) - minimum value of d
  • sum(d) - sum of values of d
  • mean(d) - mean of values of d
  • std(d) - standard deviation of d
  • pt1 = [0 1 1]; pt2 = [1 1 0];
  • dot(pt1,pt2) - dot product
  • cross(pt1,pt2) - cross product

Data Types

Matlab values/variables can take the following data types:

  • Floating Point, e.g. 1.234 (single, double)
  • Integer, e.g. 3 (int8, int16, int32, int64)
  • Character, e.g. ’a’ (char)
  • Boolean, e.g. 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

Loading and saving data

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');

Starting Programming

Visualisation

Graph Plotting

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 graph
  • xlabel('Angle in radians’); - Adds x-axis label
  • ylabel('Sine’); - Adds y-axis label
  • axis([0 pi 0 1]); - Defines figure boundaries
Matrices

It 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];
Matrix operations

There are built-in Matlab functions for initialising arrays:

  • a = zeros(2,2) - matrix of zeros
  • b = ones(2,2) - matrix of ones
  • c = eye(2,2) - identity matrix

Note the difference between matrix operations and element-wise operations:

  • d = b * c - d is a matrix of ones
  • e = b .* c - e is the identity matrix

Creating and running scripts

For complex series of operations script m-files can be very useful. Just make sure you save your script with the .m extension!

Adding Comments

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
Code analyser and debugger

Scripts do not always work first time, however to help you debug your scripts, Matlab provides two useful tools:

  • Code analyser
  • Debugger



Written by Tobias Whetton

2
Control Structures

 OPEN STANDALONE 

Flow in a program

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.

Conditional control flow

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 1true—>statement a
  • condition 1false—>statement b
if statement

The 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.

Comparison/logical operators
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
...
Operator Precedence
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 statement

Can 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

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 loops
  • while loops
for loops

for 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 loops

while 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 loop
  • while – if you don’t

Program efficiency

Often 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

Jump statements unconditionally transfer control to another part of the program. There are two types of jump statement in Matlab:

  • break statement
  • continue statement
break statement

The 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 statement

The 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.



Written by Tobias Whetton

3
Functions

 OPEN STANDALONE 

What is a function?

In mathematics we think of functions like this:

In programming, functions are a little different. In Matlab, a function can:

  • Receive Information - Input Arguments(s)
  • Process Information - Carry out Operations on input arguments
  • Return Information - Return Output Argument(s)

However all are optional, i.e. it is ok for a function to have no inputs.

Matlab functions

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
Built in functions

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.

Scope

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.

Scripts

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

More than one function in a file

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.

scratch.m
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 depth

There 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)

Error checking

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 expected
  • error: when function really cannot proceed

Below 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.

The Matlab Path

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:

  • If PWD is ’/path/to/current/directory’
  • And the function we want is in ’/some/other/directory’
  • We need to run the following at the command line: >> addpath(’/some/other/directory’)
  • Then we will be able to call our function (otherwise we will get an error)

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.

Recursive functions

Here is an example of a recursive function, it prints a message and then calls itself:

dontDoThis.m
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:

  • Stopping condition
  • Base case
  • Ground case

A recursive function with a stopping condition

For example if we define a sequence as follows:

  • Start with any number (a)
  • The next number in the sequence is… (a \div 2) if (a) is even(3a + 1) if (a) is odd.
  • Stop when we reach 1.

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.



Written by Tobias Whetton

4
Program Developing and Testing

 OPEN STANDALONE 

Errors and debugging

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)
  • Syntax Error: The typed code breaks the rules on how the language should be written. E.g in r = b*b - 4 ac there is no multiplication sign, *, between 4 and ac.
  • Run-time Error: Harder to spot as in 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.
  • Logic Error: This is the hardest to find as both the syntax is ok and there is no error when the code is run, but it does not give the correct results. It is often due to incorrect implementation of a formula or algorithm. For example, if the coder forgets about operator precedence.

Validating input arguments

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 ...

Incremental Development

When writing a program to solve a problem or model a system etc. Adopt the following steps for reliable code with fewer errors:

  1. Start with a small amount of code
  2. Test to make sure code behaves as expected
  3. Add a small amount of code
  4. Test again
  5. Repeat steps 3 and 4 until completion

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.

Tips for better code and less errors

  • Always validate the input
  • Step through the program with the debugging tool and check the values of variables as the program steps through line by line.
  • Use the increment/test approach.
  • Always seek to have working code
  • Many small functions are better than one large function.
  • Use a second script/function that calls the main program and tests it.
  • The early versions can be non-interactive working with fixed data values passed in as arguments or ‘hard-coded’ in the main function. The results for these can be pre-calculated and checked for correctness at each test. The later versions can then introduce interaction.



Written by Tobias Whetton

5
Data Types

 OPEN STANDALONE 

Data stored in memory

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.

Simple data types

The bit pattern 0100 0001 can be viewed as:

  • An integer, $ 2^{6} + 2^{0} = 64 + 1 = 65 $
  • A character, need a look up table. e.g ASCII table. i.e. 0100 0001 = A
  • There are also other data types…
Pattern Decimal ASCII Character
0011 1100 62 >
0011 1111 63 ?
0100 0000 64 @
0100 0001 65 A
0100 0010 65 B

Integers

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.

Integers in Matlab

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
Larger integers

For larger integers, we can use more bytes:

  • int16 uint16: 2 bytes
  • int32 uint32: 4 bytes
  • int64 uint64: 8 bytes

This means that it is possible to represent a wider range of integers, e.g.

>> intmax('uint16')
ans =
    65535
>> intmin('int64')
ans =
    -9223372036854775808

Floating point numbers Real Numbers

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
Floating point numbers in Matlab

These can use:

  • single: 4 bytes (32 bits)
  • double: 8 bytes (64 bits)

With the allotted bits, we need encode:

  • The Mantissa and its sign
  • The Exponent and its sign

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
Special floating point numbers

In Matlab, specific values of double can be used to represent:

  • Infinity
  • Not-a-Number (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

Logical data type Boolean

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.

Summary of data types

Character   char
Boolean   logical
Numeric unsigned integers uint8 uint16 uint32 uint64
Numeric signed integers int8 int16 int32 int64
Numeric signed floating point single double

Arrays

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

Matrix Operations

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)

Character Arrays

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

Logical Arrays

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

Converting between the types Casting

It is possible to convert from/to numeric from/to:

  • logical
  • character

However it is not possible to convert from/to logical from/to character

Converting between numeric and character types

Based on codes used to represent the characters in the look up table:

>> char(66)
ans =
    B

>> double('B')
ans =
    66
Converting between Numeric and Logical types

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

Explicit conversion

This is where the specific functions, double, char & logical are used to convert between data types.

Implicit conversion

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



Written by Tobias Whetton

6
File Input/Output

 OPEN STANDALONE 

Simple file I/O

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');

Types of external file

  • Text files - consist of sequence of characters in e.g. ASCII format.
  • Binary files - data stored in binary format (i.e. 0s and 1s), not interpreted using standard coing system.
  • MAT files - ‘native’ MatLab binary format.

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

Simple functions for text file input and output

Here are the most common functions used for text file input and output:

  • csvwrite: write data to comma-separated-value file
  • csvread: read data from comma-separated-value file
  • dlmwrite: write data to delimiter-separated file
  • dlmread: read data to delimiter-separated file

For 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.

Opening and closing files

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’: append

A more complex file open/close example

The 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);

File I/O functions

Here are a few useful functions involved with opening and closing a file:

  • fopen, close - open/close a file
  • foef - check for end-of-file condition
  • fgetl - read a line from a text file
  • fprintf - write text (to a file…)

Further file input functions

If an operator wishes to read the following systolic/diastolic blood pressure data file into a 2D numeric array:

sys_dia_bp.txt
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:

  1. fid1 - File identifier
  2. ’%d %d’ - Format specifier
  3. [2 inf] - Output array size

Here 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);

Format specifiers

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)

A more complex fscanf example

If the operator is presented with strings accompanying the data in his file, he needs to separate the information. e.g.

sys_dia_bp2.txt
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)

Summary of all I/O functions

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



Written by Tobias Whetton

7
Program Design

 OPEN STANDALONE 

What is program design?

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:

  • Deciding how to break down a program into modules
  • Deciding what the modules should do
  • Deciding how the modules should interact

Top-down vs. Bottom-up design

There are two different methodologies to software design:

  • Top-down has the emphasis on planning and complete understanding of the whole system
  • Bottom-up has the emphasis on early coding

Top-down design

This is most commonly applied in procedural programming. It is also known as stepwise refinement. The basic idea is to:

  • Break down problem into simpler sub-problems - each will be addressed by a separate program module.
  • Break down each sub-problem into even simpler sub-problems.
  • Continue until all sub-problems can be easily implemented.

A good example of this is when designing a perfect number program…

The rest of this chapter will be completed soon



Written by Tobias Whetton

8
Further Visualisation

 OPEN STANDALONE 

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.

Visualising multiple plots

Sometimes it can be useful to visualise multiple plots at once…

Method 1 multiple sets of arguments to plot

x = 0:0.1:2*pi;
y = sin(x);
y2 = cos(x);

plot(x,y,'-b', x,y2,'--r');
legend('Sine','Cosine');

Method 2 multiple plot commands on same figure

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');

Method 3 using multiple figures

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');

Method 4 using subplots

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');

Method 5 on same figure but with different y-axes

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');
A short summary of the different methods

To visualise multiple datasets on the same figure:

  • Use multiple sets of arguments to plot
  • Use hold on and multiple plot commands
  • Use subplot
  • Use plotyy if different y-scales required

To visualise multiple datasets of different figures:

  • Use the figure command to create multiple figures

3D plots

Multivariate data is data that has more than 1 value per ‘individual’, e.g.

  • Patient data: age, blood pressure, cholesterol level

Visualising multivariate data

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');

Visualising surfaces

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');

Imaging data

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 image
  • imwrite writes the array to a file
  • saveas saves the current figure (gcf) to a file



Written by Tobias Whetton

9
Code Efficiency

 OPEN STANDALONE 

Computer programs (code) can be:

  • Time efficient i.e. run very quickly
  • Memory efficient i.e. use a small amount of RAM
  • Both
  • Neither

Sometimes this is important, however often it is not. Typically, readability is more important.

Time efficiency

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
% ...
COMMAND WINDOW
>> sumOfIntegers(1000000)
Elapsed time is 0.014182 seconds.
...

The rest of this chapter will be completed soon



Written by Tobias Whetton

10
Images and Image Processing

 OPEN STANDALONE 

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



Written by Tobias Whetton