You are on page 1of 60

UNIVERSITY OF SOUTHAMPTON FACULTY OF ENGINEERING AND THE ENVIRONMENT

Institute of Sound and Vibration Research

A Refresher Course in MATLAB


Course Manual

Rachel M. van Besouw, Timos Papadopoulos, Katrine S. Rogers, Emery M. Ku and Chris J. Powles

This work is licenced under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a copy of this licence, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California 94105, USA.

January 2011

Contents

Introduction 1.1 1.2 1.3 1.4 1.5 1.6 1.7 Aims, Objectives & Learning Outcomes . . . . . . . . . . . . . . . . . . . . . . . Supporting Code Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Course Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . New Features & Demos in MATLAB . . . . . . . . . . . . . . . . . . . . . . . . Using Commands in MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arranging the MATLAB Window . . . . . . . . . . . . . . . . . . . . . . . . . . Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1 1 2 3 3 4 7 7

Programming for Correctness 2.1 Handling Warnings & Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 2.1.2 2.1.3 2.2 Try-Catch Construct . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8 8 9

MException Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 Validation Tools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Debugging Tools in MATLAB . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.2.1 2.2.2 2.2.3 M-Lint Code Analyzer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 Function Handles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 Breakpoints & Stepping Through Code . . . . . . . . . . . . . . . . . . . 15

2.2.4 2.3

TODO & FIXME Comments . . . . . . . . . . . . . . . . . . . . . . . . . 17

Assessing Code Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.3.1 2.3.2 TicToc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 Proler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

2.4 2.5

Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 Test Yourself . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

Structuring Code 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8

21

Private Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Function Handles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Anonymous Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 Subfunctions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Nested Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Precedence Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 Test Yourself . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

Structuring Data 4.1

29

Cell Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 4.1.1 4.1.2 Importing Data From a Text File . . . . . . . . . . . . . . . . . . . . . . . 30 Indexing Cell Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

4.2

Structure Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 4.2.1 4.2.2 Creation and Indexing of Structure Arrays . . . . . . . . . . . . . . . . . . 36 Dynamic Fieldnames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38

ii

4.3 4.4 4.5

Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 Test Yourself . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

Visualising Data & GUI Development 5.1 5.2 5.3 5.4 5.5

43

Object Handles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 Modifying Object Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Adding Uicontrol Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 Plot Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 Animations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 5.5.1 5.5.2 Creating a Movie using Getframe . . . . . . . . . . . . . . . . . . . . . . 50 Modifying Graphics Object Properties using Drawnow . . . . . . . . . . . 51

5.6 5.7 5.8

Graphical User Interface (GUI) development in GUIDE . . . . . . . . . . . . . . . 52 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Test Yourself . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

iii

Chapter 1 Introduction
1.1 Aims, Objectives & Learning Outcomes

The overall aims of this course are to widen your knowledge of the tools available in MATLAB, and enable you to program more efciently and effectively using relevant and hopefully motivating examples. The teaching objectives of the course are to reintroduce you to the MATLAB environment, drawing attention to the features of recent releases and helpful keyboard shortcuts; introduce efcient methods for debugging, assessing the performance of and speeding up code; provide examples of the different function and data types and explain the implications of each; and provide an overview of the visualisation techniques and graphical user interface (GUI) development tools available in MATLAB. By the end of the course it is anticipated that you will be able to:

More efciently utilise the MATLAB environment, including recent features Select and use appropriate tools for debugging and improving the efcacy of code Select and use appropriate function and data types for optimal performance Select and use appropriate methods for visualising data Implement or amend basic GUIs for research or demonstration purposes

1.2

Supporting Code Files

The MATLAB code les for this course are organised in the directory structure shown in Figure 1.1. The parent directory of each unit (e.g. 2 Programming for Correctness) contains a corresponding code le (e.g. Part2 Programming for Correctness.m) with exercises for delegates to complete, together with supporting code les and data. The parent directory for each unit also contains a sub directory called Instructor Version, which contains the model solutions.

2_Programming_for_Correctness (contains Part2_Programming_for_Correctness.m) Instructor_Version 3_Structuring_Code (contains Part3_Structuring_Code.m) Instructor_Version private 4_Structuring_Data (contains Part4_Structuring_Data.m) Instructor_Version CIPIC_hrtf_database 5_Visualising_Data (contains Part5_Visualising_Data.m) Instructor_Version
Figure 1.1: Structure of supporting code les

The supporting code les were created and tested in MATLAB version 7.11 (R2010b) and the Windows XP operating system. The shortcuts, menu commands and lepaths used here may need to be adapted for other operating systems. 2

1.3

Course Structure

1. Introduction (9:00 - 9:30) 2. Programming for Correctness (09:30 - 11:00) Coffee (11:00 - 11:15) 3. Structuring Code (11:15 - 12:15) Lunch (12:15 - 13:15) 4. Structuring Data (13:15 - 14:15) 5. Visualising Data & GUI Development (14:15 - 15:45) Coffee (15:45 - 16:00) GUI Developement Time and Q&A Session

1.4

New Features & Demos in MATLAB

To nd out that is new in the most recent version of MATLAB, navigate to: Help Product Help MATLAB Release Notes and click on the Details link in the New Features and Changes column for the latest version (see Figure 1.2).

Figure 1.2: Details of the new features & changes in MATLAB

For example, in version 7.10 (R2010a) under New Features and Changes to the Desktop Tools and Development Environment Editing and Debugging MATLAB Code you will see that the MATLAB editor now supports tab completion for local variable and subfunction names within MATLAB program les. For code and video demonstrations on the topics of: Getting Started, Mathematics, Graphics, 3-D Visualization, Programming, Desktop Tools and Development Environment, Creating Graphical User Interfaces, External Interfaces, and New Features, navigate to: Help Product Help MATLAB Demos

Figure 1.3: Code and video demonstrations

1.5

Using Commands in MATLAB

Most commands in MATLAB can be done in one of three ways; clicking in the correct menu, using a shortcut or typing a command at the command prompt. Sometimes there is also a button which can be clicked. A few common examples are given in Table 1.1. Operation Open new m-le Save le Open saved le Clear command window Clear workspace Close all open windows Shortcut Ctrl+N Ctrl+S Ctrl+O Command edit save filename open filename clc clear close all Menu File New Script File Save File Open Edit Clear Command Window Edit Clear Workspace

Table 1.1: Example shortcuts, commands and menu options in MATLAB.

The rst three of the examples in Table 1.1 can also be done by clicking the correct button as shown in Figure 1.4. Figure 1.4 shows the buttons (in ellipses) for opening a new m-le, opening an existing m-le and saving an m-le. The rst two actions can be done from the main MATLAB window or from the editor, but saving an m-le in this way can only be done from the editor.

Figure 1.4: Buttons for opening a new or existing m-le and saving It is also possible to create customised buttons for your own frequently used commands (see Figure 1.5); select the commands in the Command History window, right click and select Create Shortcut. Figure 1.6 shows the shortcut editor used to create a shortcut button called Clean Up, which executes the commands clear, close all and clc.

Figure 1.5: How to add shortcut button

Example Shortcut

Figure 1.6: Creating a shortcut

Figure 1.7: Undocking & redocking windows

1.6

Arranging the MATLAB Window

When opening MATLAB, the window may be arranged in different ways. The previous gures show that the Command Window is to the right, and to the left are the Current Directory, Command History and Workspace. Figure 1.7 shows an example where the Command History has been undocked. Ellipses show the buttons for re-docking the Command History and undocking the Workspace. These windows can also be moved within the MATLAB window by clicking on the titlebar and moving it to a preferred location before releasing the mouse button. An example of a different arrangement is shown in Figure 1.8

Figure 1.8: Arranging the MATLAB window by moving titlebars

1.7

Summary

In this introduction we have learned:

Where to access the new features and changes of the latest MATLAB release Shortcuts, commands and menu options for opening/saving les, clearing the command window, clearing the workspace and closing windows How to create custom shortcuts How to arrange the MATLAB window

Chapter 2 Programming for Correctness


The aim of this unit is to provide an overview of the tools available in MATLAB R2010a for debugging code and assessing code performance. In this unit we describe methods for diagnosing warnings and errors, explain how to use various debugging tools to verify code execution and to efciently identify and correct problems in code, and introduce methods for assessing the execution time of code. All of the code examples relate to the problem of solving the equation for a mass on a spring. By the end of this unit you will have developed skills that will enable you to: Diagnose warnings and error messages Select and use appropriate tools for addressing problems in code Select and use appropriate tools for verifying code execution Assess the performance of code Open 2 Programming for Correctness.m for the exercises in this unit.

2.1

Handling Warnings & Errors

The code examples for this section involve reading in the parameters and initial conditions for a mass-spring system. In 2 Programming for Correctness.m the following lines of code throw an error in the command window: parameters file = fopen(mass spring parameters.txt); parameters = fscanf(parameters file,%g); 8

fclose(parameters file); disp(Parameters read ok); Errors terminate the execution of the code and commands following the error are not executed (hence Parameters read ok does not appear in the command window). A simple method of determining which line of code produced the error is to comment the code one line at a time by placing the cursor at the start of the line and using the Ctrl+R and Ctrl+T comment and uncomment shortcut keys.

2.1.1 Try-Catch Construct


As a form of damage limitation, we can place the lines of code above in a try-catch construct. If an error is likely to occur in the program (perhaps due to a le name change as in this example), then alternative lines of code can be executed instead. try parameters file = fopen(mass spring parameters.txt); parameters = fscanf(parameters file,%g); fclose(parameters file); catch ME parameter file (This part is called an MException Object)

warning(PforC:parameters file, ... Unable to access file. Using default parameters.); disp([Original error message was: ME parameter file.message]); parameters = [10; 0; 15]; end The code above now thows a warning in the command window, but the code still executes in full. The warning function enables us to display a custom warning. Warning messages comprise a message identier and the actual message. Message identiers usually provide information about the source of the warning (e.g. project, program or company name) followed by a colon and then a short description or mnemonic of the warning itself, e.g. PforC:parameters file - our custom example and MATLAB:divideByZero - a message identier that you may have come across in the past. The MathWorks have now removed this particular warning from current versions of MATLAB. The message part is displayed in the command window. To retrieve the last warning message and 9 ...

message identier, use [warnmsg msgid] = lastwarn; We can also suppress the display of warning messages with a given message identifer using warning(off, PforC:parameters file); If you now execute the try-catch statement above, you will not see the custom warning in the command window. To turn the display of this warning message back on use warning(on, PforC:parameters file); To query the state of a warning message use: warning(query, PforC:parameters file); To turn all warnings off/on use warning off all; warning on all;

2.1.2 MException Object


The MException Object that we have named ME parameter le also contains information about the error generated in the try part of the construct. If you double click this object in the workspace you will see that it contains identier and message components. The message component was displayed in the command window. Messages produced by the MException Object can often be difcult to interpret, so it is useful to use custom warning messages where you can. The throw method can be used with the MException object to issue the exception and terminate execution of the program, as in the example below: try initial conditions file = fopen(initial conditions.txt); initial conditions = fscanf(initial conditions file,%g); fclose(initial conditions file); catch ME initial conditions file warning(PforC:initial conditions file, ... Unable to access initial conditions file.); throw(ME initial conditions file) end

10

Other methods that can be used with the MException object include rethrow and throwAsCaller. See MException in the MATLAB Help documentation for further details. Alternative ways of generating an error message include using the error and assert commands, e.g. filename = mass spring initial conditions.txt; initial conditions file = fopen(filename); assert(initial conditions file > 0, ... Cannot open file %s, filename); Remember that, unlike warnings, errors terminate the execution of the code. To ensure no les are left open accidentally, use fopen(all) to return a vector of all the le identiers of open les. Then use fclose(all) to close them: if fopen(all) fclose(all); end

2.1.3 Validation Tools


To check that the les contained appropriate numeric values, we can use the following validation method: if isa(parameters,double) || isempty(parameters) error(PforC:parameters file, ... The file does not contain the right data type.); end if isa(initial conditions,double) || isempty(initial conditions) ME = MException(PforC:initial conditions file, ... The file does not contain the right data type.); throw(ME); end isa is a useful method for checking whether the input variable is of a given type or class. Classes include: logical, char, numeric, integer, float, single, double, cell and struct. Functions for checking the class of variables include: iscell, ischar, isfloat, isinteger, isnumeric etc. Search for is* in the Help Documentation for a complete list. To conrm the class of a variable, use the class command: class(parameters) 11

class(initial conditions) We can investigate the data further by checking that at least 3 parameters were read in. In the example below a warning is thrown if there were more than 3 parameters and zeros are inserted if there were less than 3. if numel(parameters) > 3 parameters = parameters(1:3); warning(PforC:parameters long, ... There are more than 3 parameter values in parameters file. Only the first 3 will be used.); elseif numel(parameters) < 3 parameters(numel(parameters)+1:3) = zeros(3-numel(parameters),1); warning(PforC:parameters short, ... There are fewer than 3 parameter values in parameters file. Zeros will be used for the rest.); end In the example above we use numel to validate the number of elements in the array parameters. Another validation tool that we can use to check the validity of arrays is validateattributes. This function requires an input array, a class specication and an attributes specication. In the example below we check that there are exactly 2 initial conditions, that they are of class double, and that they are a column vector (the numbers should be read in as a column vector regardless of the format of the text le). validateattributes(initial conditions,double,size,[2,1]); See validateattributes in the MATLAB Help Documentation for a list of class and attribute arguments.

2.2

Debugging Tools in MATLAB

In this section we use analytical and numerical solutions for the equation of motion for a mass on a spring as a code example. Note that the code in this le is indented to help readability. To automatically indent your code, select the lines of code that you want to indent and use the Ctrl+I keyboard shortcut.

12

2.2.1 M-Lint Code Analyzer


m = parameters(1); c = parameters(2); k = parameters(3) mass (kg) damping coefcient spring stiffness (N/m)

u 0 = initial conditions(1); initial displacement u d 0 = initial conditions(2); initial velocity In the code above a semicolon is missing. Go to File Preferences Code Analyzer and verify that the option for Enable integrated warning and error messages is checked (see Figure 2.1). In earlier versions of MATLAB Code Analyzer Preferences was named M-Lint Preferences. M-Lint is a code checking tool. It uses a green/orange/red square indicator in the top-right corner of the editor to indicate errors, warnings and opportunities to improve code (see Figure 2.2): green: orange: red: no errors, warnings or opportunites to improve code warnings or opportunites to improve code errors

Figure 2.1: Setting M-Lint preferences If you click on the square indicator, it will take you to the next M-Lint message. Each M-Lint message is also represented by a coloured horizontal bar on the right side of the editor and if you hover over this with you mouse it will display the M-Lint message (see Figure 2.2). As soon as you address the issue, the M-Lint indicator automatically updates itself. 13

Figure 2.2: M-Lint indicators and messages You can also use the M-Lint function in the command window to display M-Lint information about a le e.g. mlint(Part2 Programming for Correctness) Or, in the editor, you can select Tools M-Lint Show M-Lint Report.

2.2.2 Function Handles


A quick detour into function handles is neccesary when using the MATLAB ordinary differential equation solver ode45. In this code example we use ode45 as follows: fh = @(t,y) odefn(t,y,m,c,k); [T,Y] = ode45(fh,[0 end time],initial conditions); where odefn is an m-le with the differential equations to be solved. The ode45 solver requires the following as input parameters:

1. a function handle that calls a function which denes the differential equations to be solved 2. a vector specifying the interval of integration (e.g. 0 to 50 seconds) 3. a vector specifying the initial conditions (displacement and velocity)

We are already familiar with the idea that a variable name can be used as a substitute for a variable, e.g. var name = 5; A function handle can be used similarly as a substitute for a function. For example: 14

fh sin = @sin; the function handle is created using the @ symbol y = fh sin(pi/2); Function handles enable a function to be passed to another function. For example: pi approx = fzero(fh sin, 3); where function fzero nds the zero(s) of the sin function near sin(3). The following also produces the same result: pi approx = fzero(@sin, 3); You can create handles to functions that are dened in m-les simply by using the @ symbol and the function name as above. It is also possible to specify the function at the same time as creating the function handle. This type of function handle is called an anonymous function handle as there is no m-le for the function. For example: fh cube = @(x) x.3; fplot(fh cube, [-2 2]); Here the function, x.3, is dened at the same time as the handle using the dummy input variable (x). The fplot command accepts function handles as an input and we can use this to evaluate the function if the form y = f(x) over a range of limits (in this case from -2 to +2). We will explore function types in more detail in Unit 3: Structuring Code and we will be using function handles in all the other sections of the course.

2.2.3 Breakpoints & Stepping Through Code


The function read file opens a le containing other values for m and assigns them, as well as the original value of m, to ms. This time OnCleanup is used to ensure that the le is not left open if an error occurs. When the following lines of code are executed, an error occurs: ms = read file(m); number of ms = length(ms); There are several ways of using the same debugging tools in MATLAB to nd errors in code. One method is to use the breakpoint and step buttons shown in Figure 2.3 to set a breakpoint, execute the lines of code up to the breakpoint and then from the breakpoint, step through the code line by line, observing the values of variables and checking the program ow. Breakpoints can also be set/cleared by clicking on the dash next to the line number of the code where you want the breakpoint. When stepping through code, the values of variables can be observed by hovering the mouse pointer over the variable name. Note that breakpoints are red 15

Figure 2.3: Set/clear breakpoint, Step, Step in, Step out, Continue and Exit debug mode buttons

Figure 2.4: Setting conditional breakpoints when the script has been saved and grey when the script has been edited and is unsaved. It is also possible to stop the execution of code and locate the error by navigating to Debug Stop if Errors/Warnings... and clicking on Always stop if error (dbstop if error). Breakpoints can also be conditional. To insert a conditional breakpoint, create a breakpoint using the set breakpoint button or by clicking on the dash next to the line of code, and then right click on the breakpoint. Select Set/Modify Condition... from the menu and enter the condition in the box (see Figure 2.4). The breakpoint will then turn yellow to indicate that it is a conditional breakpoint. The debug commands that we have learned can also be executed using the commandline. Simply type dbstep to step through the code line by line, dbstep in to step into a function, dbstep out to step out of a function and dbquit to quit debug mode. dbclear all can be used to clear all breakpoints. For a few handy shortcuts, see Table 2.1. Another useful short cut to remember is Ctrl+C for stopping code execution. For example, if you were to type pause(inf) then Ctrl+C will abort the process and bring you back to the command prompt!

16

Operation Comment code Uncomment code Indent code Evaluate selected code Step through code Step in Step out Save le and run

Shortcut Ctrl+R Ctrl+T Ctrl+I F9 F10 F11 Shift+F11 F5

Menu Text Comment Text Uncomment Text Smart Indent Text Evalaute Selection Debug Step Debug Step In Debug Step Out Debug Save File and Run

Table 2.1: Useful debugging shortcuts in the editor.

2.2.4 TODO & FIXME Comments


It is common for programmers to leave TODO, FIXME and NOTE comments in their code. MATLAB provides a TODO/FIXME report tool that enables you to quickly locate all of the mles in a folder with these comments in them. Navigate to Desktop Current Folder (if this is not already open) and click on the cog-like Actions icon (see Figure 2.6). Select Reports TODO/FIXME Report. This report lists all of the m-les in the current directory and the line numbers in each le where these comments occur (see Figure 2.5). Click on the line number for a comment to go to that line of code.

Figure 2.5: TODO/FIXME report Other reports that can be accessed in this way include: Code Analyzer Report TODO/FIXME Report File Dependency Report - Display M-Lint Code Analyzer report - List all TODO and FIXME comments - Show le dependency in the current directory

17

Figure 2.6: MATLAB report tools

2.3

Assessing Code Performance

2.3.1 TicToc
The commands tic and toc can be used to measure the time that lines of code take to execute. The time measured by tic and toc is known as clock time and is the same as if you measured the time elapsed using a stop watch. The output of tic can optionally be assigned to a variable, enabling more than one timer to be used at the same time. For example, timer1 = tic; ... timer2 = tic; ... ... time2 = toc(timer2); ... time1 = toc(timer1);

18

2.3.2 Proler
The MATLAB Proler is also a really useful tool for comparing how long different parts of a script take to run and identifying lines of code that could be made to execute more efciently. Open the proler by navigating to Tools Open proler or by using the Proler icon in the tool bar. To prole an m-le, type the name of the m-le where it says Run this code (see Figure 2.7). Double click on the m-le name in the Function Name column to see the lines of code where most time was spent. In order to only view the speed of a specic section of code you can also insert the commands profile on, profile off and profile viewer in your code.

Figure 2.7: MATLAB Proler

19

2.4

Summary

In this unit we have learned about: Handling warnings and errors using the try-catch construct, the MException object and various validation tools. Debugging tools including the M-Lint Code Analyzer, Breakpoints, stepping through code and locating TODO/FIXME comments. Assessing code performance using tic toc and Proler. For more information on any of the topics covered, try MATLABs Product Help or visit http://www.mathworks.com/products/matlab/

2.5

Test Yourself

1. True or False: Warnings terminate the execution of code? 2. Which of the following is not used as a validation tool? (A) class (B) numel (C) tic/toc (D) validateattributes 3. Which of the following M-Lint indicator descriptions is correct (A) green = opportunites to improve code (B) green = no errors, warnings or opportunites to improve code (C) orange = no warnings (D) red = warnings 4. Which of the following breakpoint descriptions is correct? (A) red = breakpoint in unsaved le (B) yellow = conditional breakpoint (C) yellow = unconditional breakpoint (D) grey = breakpoint in saved le 5. True or False: Proler displays the lines of code that take longest to execute?

20

Chapter 3 Structuring Code


The aim of this unit is to provide an overview of the methods to modularize code into readable and maintainable functions. As with most advanced programming languages, MATLAB allows for several implementation options when writing functions. There is often a tradeoff between readability and code performance that should be carefully weighed. By the end of this unit you will have developed skills that will enable you to: Describe the main features of anonymous, nested, private, and sub functions Select and use appropriate function types Apply knowledge of precedence rules for functions and variables that have the same name Open 3 Structuring Code.m for the exercises in this unit.

3.1

Private Functions

In the code les for this unit there are two functions called myPolyFun - one directly in the 3 Structuring Code directory and one in a folder called private within the 3 Structuring Code directory (see Figure 3.1). The local function returns x.2, whereas the private function returns x.3. If the current directory is the parent directory (3 Structuring Code) and myPolyFun is called from the command line, the local function executes. If the current directory is the private directory within the 3 Structuring Code directory and myPolyFun is called from the command line, the private function executes. 21

3_Structuring_Code (myPolyFun.m) private (myPolyFun.m)

Figure 3.1: Directory Structure for Private Functions If the current directory is the parent directory (3 Structuring Code) and myPolyFun is called from a function in the parent or private directory, the private function executes. If myPolyFun is called from a function in the parent or private directory, with a local variable (in this case, x) that already exists in the Workspace, the local function executes. Thus the visibility of private functions is limited. Private functions can only be called by functions in the same directory or parent folder and cannot be accessed from the command line, unless you are currently in the private directory. Any function can be made a private function by placing it within a subfolder called private. This private directory cannot be added to the MATLAB search path. Local variables take precedence over private functions, and private functions take precedence over functions in the current directory. We will learn more about precedence rules in section 3.6. To check for multiple instances of a function, use the which function, e.g. which myPolyFun -all If you omit the -all qualier, MATLAB returns the pathname of the rst function that it nds.

3.2

Function Handles

We have already come across function handles in Chapter 2, where we used a function handle as an input to the ode45 differential equation solver. Function handles can be useful for:

increasing the visibility of functions changing the interface of a function minimizing the number of function les in a given directory improving performance in repeated operations

A quick recap: the function handle is created using the @ symbol and, in this example, is stored in the variable fh sin: 22

fh sin = @sin; y = fh sin(pi/2); The function handle contains the name of the function, the function type, the location of the function and any additional data required to execute the function. To access the information stored in a function handle, use the functions command, e.g. functions(fh sin) which, in this case, returns: function: sin type: simple file:

3.3

Anonymous Functions

We also came across anonymous functions in Chapter 2. If the function is dened at the same time that the function handle is created, it is known as an anonymous function (there is no m-le for the function). Anonymous functions are dened in a single line of code. The following line denes a new function handle UnwrapAngleDeg to unwrap and convert a phase varying in radians into degrees. UnwrapAngleDeg = @(x) unwrap(angle(x))*180/pi; Again, the function handle is created using the @ symbol. This is followed by a dummy input variable, x, and then the function denition. If you check the attributes of an anonymous function handle using the functions command, the function type will conrm that the function handle is a handle to an anonymous function. E.g. attributes UAD = functions(UnwrapAngleDeg) returns function: @(x)unwrap(angle(x))*180/pi type: anonymous file: workspace: [1x1 struct]

23

Note: If any workspace variables have been dened previously, they will persist in an anonymous function until the function is redened. For example, var = 0; AddOne = @(x) x+var+1; AddOne(5) returns the answer 6. However the following lines of code also return the answer 6 as the original denition of the variable var persists in the anonymous function: var = 2; AddOne(5)

3.4

Subfunctions

Subfunctions can also reduce the clutter and ambiguity of function les in a given directory, especially for long programs, or programs with graphical user interfaces (GUIs). A simple example to show how subfunctions are implemented is given below: x = -10:.1:10; y = subfunctions(x,2); plot(x,y) In subfunctions.m: function out = subfunctions(in,type) % PRIMARY FUNCTION if type == 1 out = subfun1(in); elseif type == 2 out = subfun2(in); elseif type == 3 out = subfun3(in); end end function y = subfun1(x) % SUBFUNCTION 1 y = x.1; end function y = subfun2(x) % SUBFUNCTION 2

24

y = x.2; end function y = subfun3(x) % SUBFUNCTION 3 y = x.3; end Only the rst (or primary) function in an m-le containing subfunctions can be called from outside the m-le. The remaining functions are called subfunctions. Note: In the example above, each of the subfunctions is terminated with an end command. This is optional when the m-le only contains subfunctions and should either be used for all of the subfunctions or none of them. If the m-le contains nested functions, the end command should be used to terminate all function types in the le.

3.5

Nested Functions

Nested functions can be applied in a manner similar to subfunctions, but additionally allow the workspace variables to be shared between functions in the m-le. Similarly, large blocks of data can be shared within a workspace, thus saving on memory usage. This type of function is also particularly useful for coding GUIs. A simple example to show how nested functions are implemented is given below. Nested functions can be called by functions from the level above (e.g. in the example below, nested function 1.2 can be called by nested function 1), by other functions at the same level (e.g. nested function 1.1 could call nested function 1.2) and by nested functions at lower levels (e.g. nested function 1 could be called by nested function 1.2). Unlike subfunctions it is important to terminate each nested function with the end command.

25

random data = rand(1000); output = nestedfunctions(random data); In nestedfunctions.m: [a,b] = size(input); if numel(input)<1e6 out1 = nFun1(input); output = nFun2(out1); else output = nFun2(input); end output = nFun3(input, out2); % NESTED FUNCTION 1 function out = nFun1(in) if a==b out = nnFun1 1(in); else out = nnFun1 2(in); end % NESTED FUNCTION 1.1 function out = nnFun1 1(in) out = repmat(in,ceil(1000/a),ceil(1000/a)); end % NESTED FUNCTION 1.2 function out = nnFun1 2(in) out = repmat(in,ceil(1000/a),ceil(1000/b)); end end % NESTED FUNCTION 2 function out = nFun2(in) out = (in<0.2); end end

26

3.6

Precedence Rules

If variables, m-les and functions share the same name, MATLAB operates a set of local to global precedence rules in order to determine how to proceed. The following list indicates the order of precedence:

Local variable or nested function* Subfunction Private function Class constructor (not covered on this course) Overloaded method (not covered on this course) Function in current directory Function on MATLAB path

*If a local variable and a nested function have the same name, an error occurs.

3.7

Summary

In this unit we have learned about:

Differences between private, sub-, nested and anonymous functions. Using a function handle as a substitute for a function. Precedence rules for functions and variables with the same name.

For more information on any of the topics covered, try MATLABs Product Help or visit http://www.mathworks.com/products/matlab/

27

3.8

Test Yourself

1. True or False: Private functions can be added to the MATLAB search path?

2. True or False: Subfunctions can be accessed from the command line?

3. Which of the following function types is not dened in an m-le? (A) private (B) sub (C) nested (D) anonymous

4. Which of the following takes most precedence? (A) Subfunction (B) Nested function (C) Private function (D) Function in current directory

28

Chapter 4 Structuring Data


The aim of this unit is to introduce the cell array and structure array data types as well as the use of the multidimensional numerical array as the preferred means of manipulating and processing heterogeneous and/or multidimensional data. In this unit we use an existing publicly available database of Head Related Impulse Response (HRIR) measurements provided by the Center for Image Processing and Integrated Computing, University of California, Davis (available online from http://interface.cipic.ucdavis.edu CIL html/ CIL HRTF database.htm). We will organise the data in this database into a single data container and we will show how the data can be accessed from such a container for further processing. The CIPIC database contains the Head-Related Impulse Responses (HRIRs) of 45 subjects, including two data sets obtained with the KEMAR mannequin (Algazi et al. 2001). It also contains information about the age, sex and anthropometric data for each of the subjects (including weight and 27 dimensions describing the head, torso and pinna size and position). The data contained in the CIPIC database are also multidimensional as the HRIR is a function of time, of the individual subject, of the azimuth and elevation of the sound source and the left or right ear. The teaching objective of this unit is to describe how the cell, structure and multidimensional array data types can be used for organising the CIPIC data into a suitable data container that allows accessing them for further processing and analysis in an efcient way. By the end of this unit you will have developed skills that will enable you to: Write efcient code for importing data into appropriate data containers. Use appropriate techniques for indexing data containers. Explain the advantages and disadvantages of data container types in terms of memory requirements, efciency and accessibility. Open 4 Structuring Data.m for the exercises in this unit. 29

4.1

Cell Arrays

Cell arrays are similar to standard matrices in that they have dimensions in the same way, but they are more versatile containers as they can contain anything as elements: numbers, matrices, strings, others cells, cells of other cells, structures, etc. To create a cell array, use the cell command: simple cell=cell(2,2); To assign values to each of the four elements we need to index the cell contents using curly brackets {}. For example: simple simple simple simple cell{1,1}=5; cell{1,2}=Matlab; cell{2,1}=[1 2 4]; cell{2,2}={7;8;9};

To view the contents of the cell array in the command window, simply type the name of the cell array, simple cell which returns simple cell = [ 5] [1x3 double] Matlab {3x1 cell}.

4.1.1 Importing Data From a Text File


The le anthro1.txt lists the information about the age and weight of the 45 subjects and their unique subjectID number (see Figure 4.1). It has three headers and three columns of numerical data. In this section we read information from the le into a cell array. Check that you have a copy of anthro1.txt in your current folder. To open a text le in MATLAB we use the fopen command, which takes the form fid = fopen(filename, permission); Where fid contains the le identier. The permission options include r for read, w for write, a for append. For this example, we open anthro1.txt with read access only: 30

Figure 4.1: Format of the data in anthro1.txt fid = fopen(anthro1.txt,r); We can then read the numerical data in the three columns and store this data in a cell array using the textscan command: anthro basic = textscan(fid, %n %n %n, HeaderLines,1); The textscan command requires the le identier (fid) and information about the format of the data (in this case, three columns of oating point numbers specied by %n). Here the parameter HeaderLines is also used with a value of 1 to ensure that the SubjectID, Age and Weight[Kg] headers are skipped. Other commands that we can use in MATLAB for reading les include textread, fscanf, fread and fileread. For more information on these and other low-level le input/output functions, go to: Help Product Help MATLAB Functions Data Import and Export Low-Level File I/O We can then read the headers into a cell array. The function textscan starts reading from the point in the le where it was left from its last call. So we have to set the reading point back to the beginning of the le using the frewind command: frewind(fid) headers = textscan(fid, %s, 3); fclose(fid); clear fid; 31

Note that in the textscan command above we follow the format parameter with the value 3, which instructs the textscan command to read 3 lots of string data (specied by %s). We now have two cells: anthro basic (containing the numeric data) and headers (containing the header strings). anthro basic is a 1x3 cell, each element of which contains one of the three column vectors with the corresponding numerical data. headers is a 1x1 cell containing a 3x1 cell containing strings. Figure 4.2 is a schematic representation of how the data have been imported from the text le to these two cells. This result obtained from textscan is probably not the best way to arrange the data in Matlab variables. In the following we will see how we can rearrange the data more usefully.
anthro1.txt
SubjectID 3 8 9 10 11 12 15 17 18 19 20 21 27 28 33 40 44 48 50 51 58 59 60 61 65 119 124 126 127 131 133 134 135 137 147 148 152 153 154 155 156 158 162 163 165 Age 30 NaN NaN 35 NaN NaN NaN NaN 25 NaN 39 NaN 21 63 21 18 42 22 20 22 22 19 21 22 30 23 19 21 20 20 30 23 19 20 34 26 21 25 26 22 22 22 26 23 NaN Weight[Kg] 90.000 NaN NaN 65.772 NaN NaN NaN NaN 39.463 NaN 79.380 NaN 68.040 77.112 88.452 49.896 83.462 56.700 117.936 72.576 68.040 72.576 50.000 61.236 92.988 81.648 77.112 48.535 68.040 70.308 68.040 80.000 70.308 72.576 70.000 60.000 65.772 68.000 62.000 56.700 56.246 81.648 86.184 73.937 NaN

headers & anthro_basic (Matlab cells)

Figure 4.2: Schematic of the import from the text le to the two cell arrays.

4.1.2 Indexing Cell Arrays


Because a cell array can contain different types of data stored in various array sizes, cell array indexing is a little more complex than indexing numeric or character arrays. There are two methods of accessing data in a cell: cell indexing and content indexing. The rst returns a cell with the contents of the indexed range as elements. It is chosen using the parentheses operator (). The second returns the contents themselves (rather than the contents in a cell). It is chosen using the curly brackets operator {}. 32

For example, anthro basic(1) returns ans = [45x1 double] whereas anthro basic{1} returns the column vector stored within the rst cell: ans = 3 8 9 10 11 etc. We can also index a cell inside a cell with consecutive context indexing (using {}{}) or the data inside the matrix inside a cell with consecutive cell and content indexing. For example, if we want to retrieve the weights of the 10th-13th subjects from the anthro basic cell we can write anthro basic{3}(10:13). As another example, if we want to retrieve the string Subject from the headers cell (i.e. the rst 7 characters of the contents of the rst cell within the headers cell) we use the command headers{1}{1,1}(1:7). Now that we have seen how to access the data, we can also see how to rearrange it in more suitable ways. We can concatenate the data in one numerical array to facilitate processing (since all elements are numeric, we do not need a cell to store them). We can do this with anthro num = [anthro basic{1} anthro basic{2} anthro basic{3}]; Note that cell arrays impose a memory space overhead for their creation compared to numeric arrays. This overhead is proportional to the number of elements of the cell. Compare the byte

33

size of the anthro basic and the anthro num variables in the Workspace window (keeping in mind that they both hold the same data). If the same data are arranged in a 45x3 cell with anthro cell = num2cell(anthro num); the memory space requirement increases even further (see Figure 4.3).

Figure 4.3: Cell memory overhead. Finally, what if we want all the data (header strings and numerical data) in one cell? This can be done by creating a new cell which holds as elements the two cells (anthro num and headers) that we obtained from textscan. onecell 1 = {anthro num headers}; This works but it is unnecessarily nested (a cell containing cells that, in turn, contain strings and column matrices with numerical data). A more natural choice would be to concatenate everything to a 46x3 cell array, the rst row holding the headers and the 2:46 rows holding the numeric information. onecell = [headers{1};mat2cell(anthro num,ones(1,45),ones(1,3))]; The concatenation is effected by use of the square brackets []. Note the use of content indexing (headers{1}) in order to obtain the 3 strings contained in the 3x1 cell inside the 1x1 cell headers. Note also the use of the mat2cell command for converting the 45x3 numerical array anthro num to a 45x3 cell. For more details on the use of mat2cell see the MATLAB Product Help for: MATLAB Functions Programming and Data Types Data Types Cell Arrays mat2cell 34

Returning to the anthro basic cell, suppose we wanted to plot the age variation against the SubjectID. We only have age information for some of the subjects (see Figure 4.1) so it would be preferable to only include these cases in the plot (i.e. skip the NaN elements). Appropriate use of cell indexing allows us to do this in a vectorised way (i.e. avoiding loops): temp1 = anthro basic{2}(isnan(anthro basic{2})); figure;plot(temp1,*-) The rst line above retrieves the Age data for the indices that do not contain NaN elements and puts them into the vector temp1. The second line produces the plot in a new gure window. In order to pick the SubjectId information for labelling the x-axis, we can use cell indexing again to store the SubjectId data in the vector temp2. Again, note the use of the mat2cell command which is used to convert the numerical values to a cell of appropriate dimensions containing strings. temp2 = anthro basic{1}(isnan(anthro basic{2})); temp3 = num2str(temp2); set(gca,XTick,[1:length(temp1)]) set(gca,XTickLabel,mat2cell(num2str(temp2),... ones(1,size(temp3,1)),size(temp3,2))) xlabel(SubjectID);ylabel(Age) The result is shown in Figure 4.4 (you may have to resize the gure to see the ticklabels).
65 60 55 50 45 Age 40 35 30 25 20 15 3 10 18 20 27 28 33 40 44 48 50 51 58 59 60 61 65 119 124 126 127 131 133 134 135 137 147 148 152 153 154 155 156 158 162 163 SubjectID

Figure 4.4: Plot of age variation against SubjectID.

35

4.2

Structure Arrays

4.2.1 Creation and Indexing of Structure Arrays


The previous example showed how cells can contain literally anything from the MATLAB world, and it exemplied (just some of) the existing tools for accessing and indexing the contents of cells. However, cells are not necessarily user friendly. The main reason is that the cell container (versatile as it may be) does not facilitate the structuring of information. Another option is the stucture array data type. In the following we will collect all the information of the CIPIC database in a structure array. This structure array will have a dimensionality of 45x1 (copying the number of subjects in the database) and it will have 5 elds, one for each of the subjects id, age, sex, left and right ear HRIRs. This arrangement of the data in the structure array is depicted schematically in Figure 4.5.
cipic (45x1 Matlab structure arrary) Data for the identifier number, age, sex and Left and Right ear Head Related Impulse Responses for 45 subjects Stored in the 3 (45x1) matrices age, id (numeric) and sex (string) And In the 90 (25x50x200) matrices hrir_l and hrir_r of the workspace .mat file hrir_final.mat inside the folders subject_xxx cipic(n).SubjectID .Age .Sex .HRIR_Left .HRIR_Right

Figure 4.5: Schematic of the arrangement of the CIPIC data in a MATLAB structure array. You may want to clear the workspace. You need to have loaded anthro simple.mat on your workspace (this contains three variables with the 45 subjects id, age and sex data). We rst need to create a structure array with three elds. The struct command is used to create a structure array and dene its elds and their values. In this instance we dene only the three elds holding the id, age and sex information (we describe the creation of the remaining two elds holding the HRIR in Section 4.3). For structure arrays of dimensionality m-by-n, the values have to be given as m x n cell arrays.

36

cipic = struct(SubjectId,num2cell(id),... Age,num2cell(age),Sex,num2cell(sex)); Again, compare the combined byte size of the 3 variables id, age and sex with that of the cipic structure array. Similar to cell arrays, structure arrays impose a memory space overhead for their implementation. As with cells, structure arrays also have a unique syntax for indexing and organising data. The syntax for accessing an element is of the form struct(n,m,...).fieldname where the subscripts n, m, etc. determine the element of the array and fieldname the eld. In the specic example considered here, the array is of dimensionality 45x1 so only one index is needed. Hence cipic(30).Age will return ans = 20 and cipic(30).SubjectId will return ans = 131. You can readily verify from Figure 4.4 that this is the expected result. Again, as with cells, we can concatenate specic data from selected elds in cells or numerical arrays using e.g. {cipic.Sex}, [cipic.SubjectId], [cipic(1:10).Age]. See 4 Structuring Data.m for code examples and exercises.

37

4.2.2 Dynamic Fieldnames


In this section we will add anthropometric data to the above structure array. We use this example to introduce the concepts of:

Vectorisation in cell arrays using anonymous functions. Dynamic eldnames in structure arrays.

Open the le advanced2.m for the exercises in this section. The distribution of the CIPIC database that we are using here as an example includes an extensive set of anthropometric data for the subjects of the database, such as pinna dimensions, pinna angles relative to the head, body dimensions and pinna position, and weight. These are stored in the variables D, theta, X and WeightKilograms included in the MATLAB le anthro extra.mat which you can nd in the course material. These variables are numerical matrices, each having 45 rows and varying numbers of columns depending on the number of anthropometric measurements describing the body and pinna dimensions etc. Details about these anthropometric measurement data can be found in the le anthropometry.pdf which you can also nd in the course materials. In the example considered here we add two more elds, named Somatometry and Pinna, to our structure array. The eld Somatometry is a scalar structure having 18 elds, one for each of the 17 body dimension measurements originally in the 45x17 matrix X and one for the body weight originally in the 45x1 vector WeightKilograms. Each of these 18 elds will hold a scalar for the corresponding element of somatometric data. The eld Pinna is a scalar structure having 10 elds, one for each of the 8 pinna dimensions originally in the 45x16 matrix D (which has 8 columns for the left ear and 8 for the right ear) and one for each of the 2 pinna angles relative to the head, originally in the 45x4 matrix theta (which has 2 columns for the left ear and 2 for the right ear). Each of these 10 elds will contain a 1x2 vector holding the left and right ear values for the corresponding element of pinna-related data. As will become apparent, by arranging our data in such a way in the structure array we can use the eldnames as descriptors of the corresponding elements of data and avoid the confusing variable names D, X, etc. and the lack of information regarding which of their columns holds which element of data. We also need to create the structure array eldnames. We can do this by creating a cell with the descriptions as shown below: anthro params = { x1, head width; x2, head height; 38

x3, head depth; x4, pinna offset down; x5, pinna offset back; x6, neck width; x7, neck height; x8, neck depth; x9, torso top width; x10, torso top height; x11, torso top depth; x12, shoulder width; x13, head offset forward; x14, height; x15, seated height; x16, head circumference; x17, shoulder circumference; d1, cavum concha height; d2, cymba concha height; d3, cavum concha width; d4, fossa height; d5, pinna height; d6, pinna width; d7, intertragal incisure width; d8, cavum concha depth; theta1, pinna rotation angle; theta2, pinna flare angle; }; Ideally we want to use these descriptions (which were mark-copied from the CIPIC documentation) as eld names. However, eldnames cannot contain blanks ( ), so we need to replace with, say, . We could achieve this using nested for-loops, but this can be avoided by making use of the cellfun command for a vectorised operation in cells (similar things can be done with the structfun command in scalar structures). anthro params=cellfun(@(x) strrep(x, , ),anthro params,... UniformOutput, false); With cellfun we apply the operation described by the anonymous function dened in the rst input argument as @(x) strrep(x, , ) to the cell anthro params specied in the second input argument. More details about the use of anonymous functions and function handles are given in Unit 3: Structuring Code. The parameter UniformOutput, which is set to false (third and fourth input arguments) species whether the results of the operation applied by the function of the rst argument are such that they can be concatenated in an array without the need for encapsulation in a cell array. In our example, this is not the case, hence the value false. Look up the command cellfun in the MATLAB help for more information, 39

Now we can create the new elds Somatometry and Pinna which in turn are structures. We can use dynamic eld names drawn from the anthro params cell instead of typing the eldnames individually. Note: for the exercises in advanced2.m, the cipic structure is copied and given the name cipic all. for n = 1:45 for m = 1:17 cipic all(n).Somatometry.([anthro params{m,1} ... anthro params{m,2}]) = X(n,m); end cipic all(n).Somatometry.Weight=WeightKilograms(n); for m = 1:8 cipic all(n).Pinna.([anthro params{m+17,1} ... anthro params{m+17,2}]) = D(n,[m m+8]); end for m = 9:10 cipic all(n).Pinna.([anthro params{m+17,1} ... anthro params{m+17,2}]) = theta(n,[m-8 m-8+2]); end end By enclosing in brackets () the expressions for the eldnames (i.e. those following a dot . in the structure syntax) we specify the eldname as the string to which the expression resolves, rather than explicitly specifying the string. In this way we can pass the elements of the cell array anthro params as the eldnames of the structure.

4.3

Multidimensional Arrays

To conclude this part of the course, we import the HRIR data from the CIPIC database into the cipic structure. In the original CIPIC distribution, the HRIRs are given as two 3D multidimensional arrays for each subject (one for the left ear and one for the right ear HRIRs) with the rst dimension subscript corresponding to the azimuth of the sound source, the second dimension subscript to its elevation and the third dimension subscript to the sampled time index of the HRIR. Creating and indexing multidimensional arrays is a straightforward extension of the standard MATLAB notation with additional subscripts used for indexing, e.g. array(dim1,dim2,dim3,...). However, not all operations dened for 2-dimensional arrays are valid for arrays of higher dimension. The CIPIC HRIR data are stored in the le hrir final.mat inside the 40

standard hrir database folder included in the course material (if moved elsewhere you need to specify the data path variable accordingly). This folder contains subfolders named as subject XXX (where XXX is the subject ID). Each of these subfolders contains the data for the corresponding subject. The following piece of code goes through these subfolders one-by-one, loads the data and inputs them in the structure array: data path = CIPIC hrtf database\standard hrir database\; for n = 1:45 temp = load([data path subject ... num2str(cipic(n).SubjectId,%03.0f) \hrir final.mat]); cipic(n).HRIR Left = temp.hrir l; cipic(n).HRIR Right = temp.hrir r; end The CIPIC database includes a dummy-head as one of its subjects (KEMAR dummy-head with SubjectID equal to 165). Accessing its HRIR data is done by KEMAR = cipic(find([cipic.SubjectId] == 165)).HRIR Left; The array KEMAR that we created is a 3-Dimensional array. In order to access the HRIR corresponding to a source at 80 to the left and 45 below the horizontal plane we can use the following line of code (for the azimuth and elevation angles convention see the hrir data documentation.pdf document included in the course materials). Note that we need to use the squeeze function to reduce the dimensionality to 2D for plotting. figure;plot(squeeze(KEMAR(1,1,:)));

4.4

Summary

In this unit we have covered the following topics on Cells, Structures and Multidimentional Arrays: Reading data from a .text le into a cell using textscan. Indexing data in cells using cell and context indexing. Indexing data in structure arrays using the struct(n).fieldname syntax. Accessing and restructuring data from cells, structure arrays and multidimentional arrays. Using dynamic eldnames in structure indexing. Vectorisation in cell indexing using cellfun. 41

For more information on any of the topics covered, try MATLABs Product Help or visit http://www.mathworks.com/products/matlab/.

4.5

Test Yourself

1. True or False: The expression C(1,2), where C is a 3-by-2 cell array, will return a cell data type.

2. The data type returned by the expression C{1,2}, where C is a 3-by-2 cell array, will be: (A) a 1-by-1 numeric array (B) a 1-by-1 cell array (C) a structure (D) any data type.

3. True or False: As cell arrays can contain any data type, it is recommended to use them in every instance in place of numerical arrays.

4. True or False: The dimension of a structure array is equal to the number of elds it contains?

5. True or False: All operators and functions that take numerical arrays as input arguments work in the same way for 2D and multidimensional arrays.

42

Chapter 5 Visualising Data & GUI Development


The aim of this unit is to provide an overview of the visualisation techniques and graphical user interface (GUI) development tools available in MATLAB R2010a. In this unit we introduce the concept of a graphics object and how these objects are structured in MATLAB. We describe methods for accessing handles to objects, how to use these handles to modify object properties and how to add interactive graphics objects to gures. We will also introduce the various plot types available in MATLABs Plot Catalog and explain how to generate and export animations. Finally, we explain how to develop GUIs using the Graphical User Interface Development Environment (GUIDE). By the end of this unit you will have developed skills that will enable you to: Explain the hierarchy of graphics objects and their associated properties. Modify the properties of graphics objects using object handles. Add user interface controls to a gure. Search for, select and modify plot types in MATLAB. Generate and export animations. Develop graphical user interfaces using GUIDE. Open 5 Visualising Data.m for the exercises in this unit. For exercises 1, 2, & 3 we will be plotting equal loudness contours from the ISO 226 (2003) standard, which show the relationship between the sound pressure level (in dB SPL) and perceived loudness level of pure tones.

43

For exercises 4, 5 & 6 we will be using the CIPIC database provided by the Center for Image Processing and Integrated Computing, University of California, Davis (Algazi et al. 2001), that you used in Unit 4: Structuring Data.

5.1

Object Handles

What is a handle? In MATLAB graphics are made up of objects. Each object has its own handle (you can think of this as an address) and a set of properties which describe the function and appearance of the object. These properties can be modied by using the handle to access the object.
Level 0 Root (current MATLAB session)

Level 1

Figure

Level 2

Axes

Uicontrol

Uimenu

Uicontextmenu

Level 3

Image

Line

Patch

Rectangle

Surface

Text

Figure 5.1: Hierarchy of graphics objects The hierarchy of graphics objects is shown in Figure 5.1. The level 3 objects shown are associated with the Axes object. We will look at the user interface (Ui) objects later in this unit. Level 3 objects are often referred to as the children of level 2 objects and level 2 objects are the children of level 1 objects and so on. For more information on graphics object hierarchy, go to: Help Product Help MATLAB User Guide Graphics Handle Graphics Objects Organisation of Graphics Objects The handle to a graphics object can be obtained when you create the object or by using commands such as findobj. To obtain the handle of an object when it is created, asssign a varible to the output of the function used to create the object. For example: hline = plot(f,Lp); hline now contains the handle to the line object created by the plot function. htitle = title(60 phon equal loudness contour); htitle now contains the handle to the title text object on the current axes. hx = xlabel(Sound pressure level (dB)); hx now contains the handle to the x axis label text object on the current axes. 44

To nd handles to graphics objects we can use the ndobj command, e.g. hlineobjs = findobj(gca,Type,line); gca returns the handle of the current axes. We can obtain the handles to the gure window and to the axes using the get current gure gcf and get current axes gca handle commands, e.g. hfigure = gcf; haxis = gca; The findobj command will only return the handle of an object if the objects HandleVisibility is turned on. For the hline object above we can check that the HandleVisibility is set to on using get(hline, HandleVisibility) If the HandleVisibility of an object is turned off, we can still obtain the handle by using the findall command instead.

5.2

Modifying Object Properties

All graphics objects have a number of properties that can be modied. For text objects these propA erties include: Color, FontName, FontSize, Interpreter (for LTEX or TEX instructions), Position, Rotation and String (for a full list, see Text Properties in the MATLAB Product Help documentation). For example, to change the string property of a text object, we can use the set function: set(htitle, String, Equal loudness contours); To change the colour, style and thickness of a line object we can use the get and set functions to retrieve the properties of the line and modify them: set(hline, Color, r); set(hline, LineStyle, :); lw = get(hline, LineWidth); set(hline, LineWidth, 2*lw); To change the properties of an axes object we can use the specic handle for the axes object, or the gca command: set(haxis, XScale, log, Xgrid, on); set(gca, XScale, log, Xgrid, on); What advantages are there of using a specic handle such as haxis instead of gca?

45

Note that it is possible to change more than one property of a graphics object using the same set command. For more properties that you can modify, see Axes Properties in the MATLAB Help documentation. Here are a few quick and simple ways of changing plot options without using handles:

xlabel(x axis label) title(Title of graph) text grid legend axis off

Sets the xlabel (or ylabel and zlabel) Adds a title Adds text at a specic location Adds a grid to the plot Adds a legend Turns off the axis

To delete a gure, use the close command. Note that close is the same as close(gcf) and close all deletes all gures that do not have hidden handles.

5.3

Adding Uicontrol Objects

To make a gure interactive, we can add a user interface control such as a push button (Figure 5.2): hfigure = figure; hline = plot(f,Lp); xlabel(Frequency (Hz)); ylabel(Sound pressure level (dB)); title(60 phon equal loudness contour); set(gca, XLim, [20 12500]); hbutton = uicontrol(Style, pushbutton, String, Button,... Position, [385 300 100 70], Callback, disp(Click!)); hbutton is now the handle to a Uicontrol object, which displays on the current gure. When it is clicked, the Callback property executes the disp function, which displays the word Click! in the command window. This type of Callback is called a String Callback as the Callback property is a string of commands to execute. If we generate a second gure window, we can move this Uicontrol object by changing its Parent property: hnewfigure = figure; set(hbutton, Parent, hnewfigure); We can also modify the Callback property of this Uicontrol object: 46

Figure 5.2: Figure with Uicontrol object set(hbutton, Callback, ... set(hfigure, Color, [rand, rand, rand])); Another type of Callback that we can use is a Cell Array Callback: set(hbutton, Callback, change scale callback, gca); In this example the Callback calls a function called change scale callback. This function changes the x-axis scale from logarithmic to linear or vice versa. When using functions in Callbacks that require input arguments (such as gca in this example), the function name and input arguments need to be specied in a cell array (hence the curly brackets). The input argument, gca, is the handle to our current axes (if you have lots of gures open it is better to specify the unique handle of the axes that you want to manipulate, rather than use gca). The following example uses the KeyPressFcn callback, which enables the user to interact with the GUI by pressing keys on a computer keyboard. set(hfigure, KeyPressFcn, change scale keypressfcn, gca); For more properties that you can modify, see Uicontrol Properties in the MATLAB Help documentation. 47

5.4

Plot Types

MATLAB plot functions can be categorized by the dimensionality of the data to be plotted, e.g. 1-D (vector): 2-D (matrix): 3-D (volume):
0.8 0.6 0.4 0.2 Magnitude 0 Subject 3: left ear HRIRs at 0 deg. elevation -0.2 -0.4 -45 -0.6 -0.8 Degrees Azimuth

plot, hist, stem imagesc, mesh, surf, plot3 isosurface, contourslice


Subject 3: left ear HRIR at 0 deg. azimuth and 0 deg. elevation

2 0 Time (ms)

5 Subject 3: left ear HRTFs at 0 deg. elevation

45 4 3 0.5 1 2 1 0 0 0.5 1 x 10
4

1.5

2 2.5 Time (ms)

3.5

4.5

100 50 1.5 2 2.5 Frequency (Hz) -100 -50 Azimuth (degrees) 0

Figure 5.3: Examples of plot, imagesc & surf Figures. For more plot functions have a look at the list of plots in the MATLAB help documentation (see Figure 5.4 Help Product Help MATLAB User Guide Graphics Plots and Plotting Tools Figures, Plots, and Graphs Types of MATLAB Plots Alternatively, to interactively experiment with different plot functions, choose the variable in the Workspace that you would like to plot and open the Plot Catalog by clicking on the Plot Selector icon in the Workspace menu bar (see Figure 5.5).

48

Figure 5.4: List of plots in the MATLAB Help documentation

Figure 5.5: Plot Catalog

49

5.5

Animations

Animations can be generated in MATLAB by saving a sequence of plots using the getframe command to generate a movie or by modifying the properties of graphics objects and updating them using the drawnow command.

5.5.1 Creating a Movie using Getframe


Create the axes, labels and x the axes limits plot(t, squeeze(hrir l(1,9,:))); set(gca, XLim, [t(1) t(200)], YLim, [-1 1], ... NextPlot, replacechildren); xlabel(Time (ms)) ylabel(Magnitude) title(Subject 3: left ear HRIR from -80 to +80 degrees azimuth) for k = 1:length(azimuths) plot(t,squeeze(hrir l(k,9,:))); M(k) = getframe(gca); end movie(M) Here we change the NextPlot property of the current axes object from replace to replacechildren. This ensures that the previous line object is removed before the next line object is plotted, but without resetting the axes. The getframe command returns a movie frame. A movie frame is a struct with two elds; cdata (the image data) and colormap. movie(M,n,fps) plays movie M n times at a frame rate of fps frames per second (the default frame rate is 12 fps). To export the video as an AVI (audio/video interleaved) le you can use the movie2avi conversion function, e.g. movie2avi(M, mymovie, fps, 15); Here movie M will be saved as mymovie.avi with a framerate of 15 fps. Alternatively, you can create an AVI le object using the avifile function and add frames to this object in the for loop: 50

Create the avi le object aviobj = avifile(mymovie.avi,fps,15); Create the axes, labels and x the axes limits plot(t, squeeze(hrir l(1,9,1))); set(gca, XLim, [t(1) t(200)], YLim, [-1 1], ... NextPlot, replacechildren); xlabel(Time (ms)) ylabel(Magnitude) title(Subject 3: left ear HRIR from -80 to +80 degrees azimuth) for k = 1:length(azimuths) plot(t,squeeze(hrir l(k,9,:))); M(k) = getframe(gca); aviobj = addframe(aviobj,M(k)); end Close the avi le object aviobj = close(aviobj);

5.5.2 Modifying Graphics Object Properties using Drawnow


figure; surf(f,azimuths,HRTF(:,1:length HRIR/2)); Viewing angle in degrees for anticlockwise rotation (not the azimuth angle of the HRTF): az = [pi/2:0.01:4*pi/2]*180/pi; axis off for k = 1:length(az) Use view [az el] command with azimuth and elevation input parameters: view(az(k), 60); drawnow end Here we use the view command to animate rotation of the viewpoint in an anticlockwise direction about the z axis. We could also use the axes object camera properties (e.g. CameraPosition) or the rotate and rotate3d functions to interactively rotate the axes. drawnow forces the gure window to update in the loop. If it is commented out or left outside the loop, the gure is updated at the end of the loop and only the nal frame is visible.

51

5.6

Graphical User Interface (GUI) development in GUIDE

In section 5.3 we began to create very simple GUIs by adding a push button uicontrol object to a gure. We can also quickly create GUIs by using MATLABs Graphical User Interface Development Environment (GUIDE). Open GUIDE using the command guide in the command window. This opens a quick start window where you can choose to create a new GUI or open an existing one. ELC GUI.fig is a simple GUI that displays equal loudness contours. Open ELC GUI.fig in the GUI Layout Editor. On the left hand side of the Layout Editor are buttons for selecting graphics objects. In the main window of the Layout Editor is the half nished GUI called ELC GUI.fig (see Figure 5.6).
M-file Editor Property Inspector

Figure 5.6: ELC GUI.g in the Layout Editor ELC GUI.fig has an axes object, a popup menu, a push button, two radio buttons and various text objects. Select the axes object and then click on View Property Inspector, or click the Property Inspector icon in the toolbar at the top of the Layout Editor, or simply double click the object. The Property Inspector shows all of the properties and settings for the selected graphics object, and you can modify these properties (see Figure 5.7). Find the Tag property for the axes object. You will see that this property is set to axesELC. This 52

Figure 5.7: Property Inspector is a user-specied label and we can use this to access the axes handle to modify the axes object in the code for the GUI. If you leave the Property Inspector open and click on other graphics objects in the GUI, you will see their properties. Now click on View M-le Editor, or click on the M-le Editor icon. This opens the code le for the GUI. In the M-le Editor, click on the f() show functions icon. This lists all the object create and callbacks functions. In ELC GUI OpeningFcn you will see default properties for the radio buttons and axes object, which are set as the GUI is created. The handles structure for the GUI is updated using the command, guidata(hObject, handles); where hObject is the handle of the object whose callback is executing. Variables created within a callback function are local to that function and cannot be accessed by other functions. To access the properties of other objects, we can use the get and set functions with the Tag property of the object. Note: if the properties of objects are modied using the set command, the handles structure for the GUI must be updated in order for these changes to be seen by other functions. To run the GUI, click the green arrow icon or by type ELC GUI in the command window. 53

To run a nished example, type Final ELC GUI in the command window. Open CIPIC GUI in GUIDE (see gure 5.8). This GUI has two axes, one popup menu, a number of text box objects and two editable text boxes (note: the Enable property of these text boxes has been set to off so they appear greyed out and the user cannot enter data).

Figure 5.8: Basic CIPIC GUI layout Open the m-le for this GUI using the pencil-pad M-le Editor icon and inspect the code. In the CIPIC GUI opening function, CIPIC GUI OpeningFcn, you will see handles.cipic = getfield(load(CIPIC GUI data.mat), cipic); This line of code loads the CIPIC struct that you saved as a .mat le in Unit 4: Structuring Data, and saves it in the handles structure of the GUI. After loading the CIPIC struct, the subfunction updatePlots is called with the handles structure as an input: 54

updatePlots(handles); Every time this subfunction is called, it gets the currently selected subject from the popup menu object with the tag menuSubject and uses this information to locate and display the age and sex of the subject in the editable text boxes. The subfunction then plots the left and right HRIRs for the subject for an azimuth of 0 degrees and an elevation of 0 degrees. To run a nished example, type Final CIPIC GUI in the command window. For more information on creating GUIs using GUIDE, see Creating GUIs with GUIDE in the MATLAB Help documentation.

5.7

Summary

In this unit we have learned about:

MATLAB graphics objects, object hierarchy and object handles. Using object handles to access and modify object properties. Making interactive gures or GUIs using Uicontrol objects The 1-D, 2-D and 3-D plot functions that can be accessed in MATLABs Plot Catalog. Generating animations using the getframe command and by modifying object properties and updating them using drawnow. Graphical user interface development in GUIDE.

For more information on any of the topics covered, try MATLABs Product Help or visit http://www.mathworks.com/products/matlab/

5.8

Test Yourself

1. A Uicontrol object is a child of which object? (A) Axes (B) Figure (C) Image (D) Uimenu

55

2. Which of the following would you use to return the handle of an object if the HandleVisibility of the object is off? (A) find (B) findall (C) findobj (D) findfigs

3. Which of the following would you use to plot data stored in a vector? (A) plot (B) imagesc (C) surf (D) isosurface

4. True or False: AVI les can be generated using the drawnow command?

5. Which of the following is not an interactive Uicontrol object? (A) checkbox (B) edit (C) slider (D) text

6. hObject is (select one) (A) the handles structure of the GUI (B) the handle of the object whose callback is executing (C) a type of graphical object (D) a graphical object property

References
Algazi, V.R., Duda, R.O., Thompson, D.M. & Avendo, C. (2001) The CIPIC HRFT database. 2001 IEEE Workshop on the Applications of Signal Processing to Audio and Acoustics, 99-102. ISO 226 (2003) Acoustics - Normal equal-loudness-level contours (second edition). International Organization for Standardization, Geneva.

56