"Data flow and control flow" How to structure a big problem: • Data flow: o Which types of data should be processed? o Where does the data come from? Possible data sources are: Matlab data files Other types of data files (data import) Measurement hardware User inputs Function input parameters o Where does the data go? Possible data sinks are: Matlab data files Other types of data files (data export) Hardware control Graphic Sound Text output Function output parameters o If you have structured your algorithm into sub-parts, think about which part needs which data and how the data should be transferred between the parts. • Control flow: o Most important principle “divide and conquer” o First divide your big task (coarsely) into smaller sub-tasks o For each of the sub-tasks define the input and output data, depending on the data flow you can decide to use one big program or to encapsulate sub-tasks into functions (or into separate scripts) o Could some of the sub-tasks also be used in other contexts? If yes: Encapsulate them into separate functions o Divide each of your sub-tasks into even smaller units. These can become cells of program code in Matlab. o It is a good idea to first write a separate file for each sub-task you want to program, in which you define the task and its inputs and outputs in the help text. The sequence of sub-sub-tasks leading to the solution of the sub-task can be defined as cell titles. o Which control elements (e.g. loops, case differentiation) are needed to solve the sub-sub-tasks? o Try to avoid spaghetti code, aim for lasagna code! • Creating your own toolbox o If you consider your set of scripts and functions to be (more or less) complete and ready to use, you can place them in a new subdirectory e.g. MyToolbox in the toolbox directory to permanently include them into your Matlab search path. o Write two additional files containing only Matlab comments: Contents.m lists all m-files contained in the toolbox (with input and output arguments). The first line in the Contents.m file should spacify the name of the toolbox, the second line the toolbox version and date. The command helpwin MyToolbox will display this file in the Matlab help window. Readme.m describes late-breaking changes or descriptions of known bugs or undocumented features. The command whatsnew MyToolbox will display this file in the help window. Graphical tools to structure data flow and control flow See blackboard pictures and refer to wikipedia: Control flow: http://en.wikipedia.org/wiki/Flow_chart Data flow: http://en.wikipedia.org/wiki/Data_flow_diagram Scripts and functions • Scripts o Sequence of commands, equal to typing the sequence in the command window o Variables in a script are present in the workspace o All workspace variables can be used in a script o Workspace variables can be changed and cleared in a script o Scripts are saved as .m files (you have to give them a name) o To call a script, the name of the file is used o Convenient way to make a sequence of commands reproducible. • Functions o Sequence of commands, using a separate workspace o Workspace variables, which should be used in the function have to be given to the function explicitly with input arguments, all other workspace variables are not visible within the function o Function variables, which should be used in the workspace after the function is executed, have to be given to the workspace explicitly by output arguments o The first line in the function file, the function-declaration line, defines the number and names of input and output arguments (all combinations are possible). It must contain the key word function and the function name function blabla % function without input and output function blabla (in1) % function with one input argument function out1=blabla % function with one output argument function out1=blabla (in1) % function with one in- and one output function [out1,out2]=blabla (in1,in2,in3) % function with 3 in- and 2 outputs o When saving the program, Matlab will suggest the function name as standard file name (in this case blabla.m). It is good style to use the same name for the file and the function-declaration line of the function (otherwise it can get very confusing.) o To call a function, you need to type the filename followed by as many input arguments as you have specified in the function-declaration line of the file. (If you have used a different file name than the function name in the function-declaration line, you need to use the file name.) You also should give as many output arguments as you have specified, otherwise this information will get lost. E.g. call your function with [a,b]=blabla(A,B,27.5); (with A and B variables you have defined before) o It does not make sense to define input arguments in the functiondeclaration line, which are not used in the function commands! It also does not make sense to define output arguments, which do not get assigned a value during the function execution! o Functions are the best way to solve a task with defined input and output data, without interfering with workspace variables. • Sub-functions: If you have specified a sub-task with defined input and/ or output arguments, which is used more than once in your algorithm, you should encapsulate this sub-task into a function. However, if you are sure that you will not need this specific sub-task in any other programming project, but only as part of the function you are currently working on, you can define a sub-function. Sub-functions are placed in the same file as the main function after the end statement of the main function program code. They can be called from anywhere in the main function, but they cannot be called from outside the m-file. Subfunctions have their own workspace and communicate with the parent function only via the input and output arguments. Sub-functions begin with a standard function statement line and follow all rules applying to functions. It is good style to start the sub-function name with local_ to remind the user that it is a local function. To display the help text of a sub-function, you can use helpwin parent_function/local_sub_function Syntax: function out=parent_function(in) % parent_function description % code in parent function, calling local_sub_function end % of parent_function function nout=local_sub_function(nin) %local_sub_function description %code in local_sub_function working on separate workspace end % of local_sub_function Using the cell mode in the editor • Cells are usually short blocks of program code belonging together to solve a sub-task. • Cells are marked by %% in the line before the program lines start. • %% can be followed by a comment. These comments are displayed in bold, a very convenient way to have titles for programming blocks. • You can run individual cells without the rest of the program by clicking on the cell (the current cell is marked in yellow) and clicking on the symbol “arrow right on yellow block” • To run a cell and to continue running afterwards, click on the symbol “arrow down from yellow block” • To run the entire program, click on the symbol “red arrow down” (or the regular green arrow symbol in the bar above) • In Matlab 2008, the display of cells can be compressed in the editor to just the title line by clicking on a little minus symbol left of the title line Control flow elements The flow of a computer program can be controlled by using decision-making structures to decide if certain commands are executed or not. • If-else-end construction: Executes a group of commands depending on a logical value. Very often, the logical value is the result of a relational test. More than two alternatives how to continue the program can be given by using elseif statements. Syntax: % simple conditional construction: if expression commands %evaluated if expression is true end % two alternatives construction: if expression commands %evaluated if expression is true else commands %evaluated if expression is false end % more alternatives construction: if expression1 commands %evaluated if expression1 is true elseif expression2 commands %evaluated if expression1 is false and expression2 is true elseif expression3 commands %evaluated if expression1 and expression2 are false and %expression3 is true …. else commands %evaluated if no other expression is true end • Switch construction: If several different cases should be considered, it is often clearer and more convenient to use a switch construction instead. Switch constructions allow at most one of the command groups to be executed. Switch constructions are particularly convenient if you are comparing strings (to compare two strings you usually need the function out=strcmp(string1,string2), string1==string2 does not work). Syntax: Example: switch test_expression switch units %convert x to cm case test_expression1 case ʻinchʼ commands y=x*2.54 case {test_expression2, test_expression3} case {ʻcmʼ,ʼcentimeterʼ} commands …. otherwise commands end y=x … otherwise error(ʻunknown unitʼ) end • Try-catch-block: A try-catch block provides user-controlled error-trapping capabilities. In the try-part, all commands are executed. If no Matlab errors are generated, the program continues after the end statement. If an error is generated, the program does not terminate with red lines but executes the commands in the catch-part, making it possible to react to errors in a more specific way (with more specific error messages or maybe with fixing the reason for the error). Syntax: try commands1 catch commands2 %executed only if commands1 issue a Matlab error end • For loop: repeats to execute a group of commands for a fixed, predetermined number of times. A group of commands is executed once for every column in a given array. The most common use is a counting variable (e.g. x=1:10) Syntax: for x=array commands %executed once for every column in the array end • While loop: A while loop executes a group of commands an indefinite number of times, depending on the evaluation of a test-expression. Variables used in the test-expression must be defined before the while loop starts and their value should be able to change during the execution of the command block (otherwise the loop will never terminate). Syntax: initialize x while expression depending on x commands %executed as many times as expression is true command to change value of x end Special cases of data flow • Functions with variable number of input arguments: Many of the functions provided by Matlab can be used with a variable number of input elements (e.g. plot(x), plot(x,y), plot(x,y,ʼrx-ʻ),…). You can use variable numbers of input arguments, e.g. to allow optional arguments, in your own functions by using the keyword varargin as last input argument in the function-declaration line. The argument varargin is a predefined cell array whose ith cell is the ith argument, starting from where varargin appears. In the program, you can access e.g. the 3rd optional argument with varargin{3}. Moreover, Matlab will provide the number of input arguments by using the function nargin. Syntax example: function a=testfunction(in1,varargin) %Explanation comments if nargin>1 %if there is at least one optional input argument disp(varargin{1}) % the first optional argument is displayed end • Functions with variable number of output arguments: You can always call a function with less output arguments than you have specified for the function (e.g. if you call a function without specifying output variables in the function call and without semicolon at the end, only the value of the first output argument will be stored in ans.) However, if some functions use a control flow depending on the number of output arguments, e.g. the hist function will display a figure if you call hist(x) but will not display a figure but give back the histogram values if you call a=hist(x). To write a program with a variable number of output arguments (optional output arguments), use the keyword varargout as last output argument in the function-declaration line. Varargout is a predefined cell array whose ith cell is the ith argument, starting where varargout appears. You access the ith output argument with varargout{i}. The function nargout gives back the number of output arguments used. Syntax example: function [a,varargout]=testfunction(in1) %Explanation comments if nargout>1 %if there is at least one optional output argument varargout{1}=in1/100; % assign a value to the first optional argument end • Global variables: Usually, encapsulation is a very useful and powerful concept, making sure that functions are not able to interfere with the base workspace. However, in some cases it might be more convenient to have a certain variable available in all (or many) functions of a program package (e.g. your own toolbox), without the need to pass them as input argument to each function (and to take care of the correct sequence of input arguments etc.). In this case a global variable can be used. However, the use of global variables is strongly discouraged!!! In my opinion, they only make sense for constants, which are never changed by any of the functions they are used by. It is good style to use names with all capital letters for global variables. A global variable has to be defined in a workspace and declared global in this workspace and all functions called by this script or function, which should have access to the global variable. Syntax: global MYCONSTANT • Nested functions: Nested functions are functions, which are fully contained in the definition of another function. They can have specified input and output arguments, but they also have access to all variables in the parent function. Nested functions can by called from anywhere in the function code, even though they are usually defined at the end of the main function. Nested functions cannot be called separately from other functions, scripts or the command window, only from within the main function. Nested functions are a way to avoid global variables, but they usually make the code more difficult to read and to debug. Usually, there is no need to use them – I would discourage their use! (Nested functions are allowed in version 7.0 and up.) Syntax: function out=parent_function(in) % parent_function description % code in parent function, calling nested_function function nout=nested_function(nin) %nested_function description %code in nested_function can access all variables in parent_function in %addition to explicit input argument nin) end % of nested_function end % of parent_function Homework: • Draw a control flow chart of your own program. It may be necessary to draw more of one chart on different levels of abstraction if you have a complicated program. • Draw a data flow diagram for your program