Tips and Tricks for Matlab

by Patrick Kano



[Note: the slides from Patrick's presentation in a .ps format are available here.]

MATLAB is a high level language and computing environment for scientific and mathematical problems. It was initially developed by Cleve Moler in the late 1970s to provide access to the Fortran linear algebra software packages EISPACK and LINPACK. The name, from Matrix Laboratory, reflects this origin in linear algebra. Since then MATLAB has developed into a great tool for trying out new ideas and fidgeting with algorithms. It has excellent graphics capabilities and an easily understood syntax. It also has some wonderful features that are less commonly used such built in ODE-solvers, dialog boxes, and commands for constructing graphical user interfaces. It is also possible to generate new commands written in C or Fortran that MATLAB can interpret. To understand these features it is however first necessary to have some familiarity with MATLAB's basic commands. If you are not familiar with these or if you are like me and constantly forget the syntax, then a good place to look is the SWIG page Matlab Introduction or the website by the company which owns MATLAB The MathWorks, Inc.. In the following, I assume that you have already had some exposure.

The files that I use for illustrating some of these not-so-well-known tools are provided in the link SWIG Talk Files. As usual, I make no claims that these codes are perfectly correct. In fact, I doubt it since most are cutout of larger codes. I should also point out that they were written using MATLAB version 6 installed with Linux. I have found that, in general, almost all of MATLAB's commands work perfectly in both Linux and Windows. However, there are always a few quirks when running MATLAB on different operating systems. There are also probably better ways to do much of this than as I have written it. I hope that they will provide simply a starting point for your own scripts.


Dialog Boxes

The phrase that comes to my mind when I work with MATLAB is proof of concept. If I want to demonstrate to my adviser or myself that a concept is fundamentally correct, then I can code it and debug it quickly in MATLAB.

It is often the case however that the algorithms I am using have tunable parameters which need to be adjusted by the user. Since another person is usually not familiar with the variables in the script, I normally prefer that they do not open the file containing the algorithm. Input boxes and messages can be one way of avoiding this problem. They also be very useful in the classroom or a talk. Everyone likes something nice and flashy between the equations.

One way to avoid others editing your code is to provide graphical input and output by means of dialog boxes and requesters. MATLAB makes a slight distinction here between dialog boxes which provide information and requesters which accept information. For our purposes, we simply refer to both as dialog boxes. One could develop on a very basic level their own graphical user interface (GUI). This is the next topic. However, I have found that MATLAB's own built-in/ready-to-go dialog boxes are almost always sufficient for my needs. These commands have names that typically end in dlg, such as errordlg, inputdlg, and questdlg. There are also simples things like message boxes msgbox. MATLAB's helpdesk can provide you with the details of the input to these functions. Typically, one provides a title for the box, a message to the user, default parameter values, and variables names.

In the SWIG Talk Files ExpAdvectInputFunc.m and ExpAdvectModule.m I demonstrate the use of three of these commands, inputdlg, msgbox and questdlg. The program is a simple advection equation solver. It uses explicit Euler and the full matrix exponential to propagate the system of ordinary differential equations one obtains from a center-difference approximation to the spatial derivative. The error reported in the code is the absolute error of the propagator; that is, this is the difference between the matrix exponential solution and the explicit Euler solution.

Go ahead now and run the script. Open MATLAB and at the prompt type ExpAdvectModule. At this point, a nice little message should pop up. This will wait for you to close it or push OK. The icon in the figure is easy to make. The commands are simply

Idata = (-pi/4):0.1:(pi/4);
Idata = (cos(Idata)-cot(Idata));
uiwait(msgbox('Welcome to the Advection Program','Hello','custom',Idata,pink(size(Idata,2))));

The inputs are self-explanatory and you can modify the icon data to come up with more interesting figures. Important here is the command uiwait. One of the major issues with dialog boxes and GUIs in general is controlling the flow of the code. uiwait tells the program to wait for the user to either close the figure or push 'OK'. Without this, the code will continue to the next line and the user might not see your groovy icon.

Now push 'OK'. Next should come up the inputdlg box that asks for the simulation parameters. This box is not as simple as the previous and thus I wrote a second function ExpAdvectInputFunc.m specifically for it. The function itself is called with the single line

[NTSteps,DeltasRatio,XLength,DeltaX,ICFunction] = ExpAdvectInputFunc;

The five variables I have allowed to be global variables so that they are visible to both functions. In general, one is discouraged from using global variables in MATLAB but this is one case where I have found them particularly useful. Keeping them global and writing the separate input function also helps me to determine what the simulation parameters are.

In the input function, the input dialog box is created with the line

inputdata = inputdlg(prompt,dlgTitle,lineNo,defaultvalues,AddOpts);

The inputs are again fairly simple to understand. The file also contains comments to describe them. More important is the format of the output from the dialog box. It is simply a list of strings, not numbers. Thus, one must first assign variable names to the strings. This is done with the command

inputdata = cell2struct(inputdata,fields);.

After this, one needs to convert the strings to numerical values using a command like

XLength = str2num(inputdata.XLength).

After you have selected your parameters and initial condition and hit 'OK', the code will then ask you if you wish to plot your results. Plotting is usually a very expensive process and thus there are many times when I do not want to plot the simulations as they evolve. This box is easily constructed with the command

Reply = questdlg('Plotting','Plot?','Yes','No','Yes');

The string output from the dialog box is then used to define a switch variable.

if(strcmp(Reply,'Yes')==1)
PlotSwitch = 1; %On
else
PlotSwitch = 0; %Off
end

If you choose to plot, the code will generate two figures. The first uses subplot to show together the solutions from explicit Euler and the matrix exponential. The second is of the absolute error. One should see the Gaussian initial condition scroll around the domain.


Graphical User Interface

The dialog boxes that MATLAB provides ready-to-go are great. As I said, I usually can do just about anything I want with only these commands. There are however more sophisticated graphical objects available. Constructing a GUI from scratch is not easy, thus MATLAB has a built-in GUI editor for creating GUIs called GUIDE. More about GUIDE can be found on the main MATLAB website. I have found this program useful for constructing very simple GUIs but it can also be overkill. In the following I will show you I have used both MATLAB's dialog boxes and basic GUI commands together. First however, here are a few really good examples of MATLAB GUIs:

The MATLAB files for this example begin their names with Swiggui. Go ahead in MATLAB and type at the prompt: clear all. This will remove the variable from the previous example. Now type: Swiggui_Main. Up should pop a new figure with five buttons. You may need to resize the figure to see all the buttons. This example is taken from a larger interface where there are further images to the right of the buttons which arise when the buttons are clicked. To make the code readable, I have reduced it to simply take input from the user for a simulation and write it to a data file.

At this point, open the file Swiggui_Main.m. You will see that I have again used global variables. The different buttons in the GUI allow the user to access different collections of these variables and each button has its own function telling it what to do. Reading down the file, one finds that I have also added the function Swiggui_Default_Values. I find that it helps to keep things organized to put the default values for the parameters in their own file.

Continuing to read down the function, we come across our first new object.

Hc_frame_1 = uicontrol(gcf, ...
'Style', 'frame',...
'Units', 'pixels',...
'Position', [25 250 200 230]);

The statement uicontrol is a generic command for graphical user input. The first line tells MATLAB to get the current figure, that is the GUI. The second tells MATLAB that this particular uicontrol object is a frame; it is simply a background box. For the units, I have chosen pixels and the position I have set manually. Setting the positions by-hand without GUIDE can be a pain but also very liberating. The three dots after each line are not necessary. In general, these three dots tell MATLAB to continue the command on the next line. Without them MATLAB will think that the command is incomplete.

A more interesting animal is the next object in the code, a text box.

Hc_text_Title = uicontrol(gcf,...
'Style', 'text',...
'Units', 'pixels',...
'Position', [25 500 200 12],...
'String', ['Graphical User Interface'],...
'FontSize', [10.0]);

The inputs are again very similar as to the frame. Note however that the "Style" option is now "text". This simple box I have used merely to give the name of our GUI.

Finally, we get to the push buttons.

Hc_button_Write_Parameter_File = uicontrol(gcf,...
'Style', 'pushbutton',...
'Units', 'pixels',...
'Position', [25 450 200 15],...
'String', 'Write',...
'Callback', 'Swiggui_Button_Write');

Most important here is the "Callback" option. It is this option which tells MATLAB what to do when the button is pushed. In particular, the Callback option sends the string given to MATLAB's eval command. In this case, I have told it to execute the function to write the data to a file.

That is pretty much it for the basic GUI commands for this example. There are many more styles to choose from such as

Again, one of the major difficulties with GUIs is controlling the flow of the script. Thus, I try to use MATLAB's built in functions as much as possible. Go ahead now and push the "physical parameters" button. Up should come a standard input dialog box, coded as we did in the previous section. A more interesting object is the list dialog box listdlg that one gets when they hit the "computation parameters button". If you play around with the GUI, you will find that by separating the GUI functions thematically one is able easily to incorporate dialog boxes of different types. Finally, if you hit "write" you will see that the GUI terminates and writes the file RunParameters.dat containing the input parameters.


Mex Files

The last topic to discuss are MEX files or MATLAB Executable files. To quote MathWorks, MEX-files are dynamically linked subroutines produced from C or Fortran source code that, when compiled, can be run from within MATLAB in the same way as MATLAB M-files or built-in functions. When considering that MATLAB originated as a way to easily access Fortran libraries, it is perhaps not too surprising that MATLAB can utilize code written in lower level languages. The details of how to this however are not trivial and I can only give some insight here from my own attempts. Also, since I am more familiar with C, my examples are written in this programming language. The relevant files are: xdotyMex.c, RealTridiagSolverMex.c, LagClenshawAlgorithm.m, LagClenshawMEX.c, and LagClenshawTest.m. Again, a good reference to start from is the SWIG page SWIG MEX. Another is the MathWorks site MathWorks MEX Website .

Just looking at the LAPACK command for inverting a tridiagonal matrix

zgtsv_(&NXNodes,&NRHS,DLArray,DArray,DUArray,Gvector,&LDB,&INFO);

it is clear why MATLAB has become so successful. While this commands is not horrid to implement, it is also certainly not as efficient as simply typing in MATLAB A\b. There is however an advantage of directly coding in C or Fortran and that is speed. MATLAB often runs much more slowly than a comparable program in C or Fortran, especially when computing for loops. This is not really surprising however since MATLAB was designed originally for linear algebra packages and not for the large scale simulation of differential equations. The point then is that there are situations where one has either a need for faster computations or code in C or Fortran and would simply like to implement it within MATLAB.

Every C MEX file has the follow 5 things:

mxArray One of the really nice features of MATLAB is that one does not need to predefine variable types. Thus, when translating information between MATLAB and a C code, one needs an intermediate variable. The mxArray is the central structure that one uses for all data types, including matrices, vectors, and scalars. It contains all the necessary information such as the variable formats (characters or complex double precision number), the variable dimensions, and of course the data.

mex.h and API functions The header file mex.h has the prototypes for the functions that C uses. There are two basic types of functions mx* and mex* which together constitute the API (Application Program Interface) functions. mx* functions are used to manipulate data within an mxArray. These are primarily memory management tools and should be used in place of the common commands in C. The mex* functions do everything else that you might need.

mexFunction The object which allows one to go between MATLAB and C is the gateway function

void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )

All C MEX files must have this command just as every standard C code must have a "main" function. The inputs are important to understand, the following table is taken from the MathWorks MEX website:

MexFunction Name of the gateway routine (same for every MEX-file)
nlhs Number of expected mxArrays (Left Hand Side)
plhs Array of pointers to expected outputs
nrhs Number of inputs (Right Hand Side)
prhs Array of pointers to input data. The input data is read-only and should not be altered by your mexFunction .

C Function to Compute In addition, one must of course have a function in the C code which performs the desired operation. The name of this function is also the name of the command for MATLAB. Thus for example, if the C function is called kanowins and has input onecow, then in MATLAB one would type at the prompt kanowins(onecow)

With these basic concepts, we can write simple programs. At this points, lets open the file xdotyMex.c. This function computes the dot product of two vectors. The corresponding commands from MATLAB are sum(u.*v). At the top of the file containing the C code, I have placed the example:

>> mex -g xdotyMex.c
>> VecOne = [1 2 3 4]
VecOne =
1 2 3 4
>> VecTwo = [4 5 6 7]
VecTwo =
4 5 6 7
>> xdotyMex(VecOne,VecTwo)
ans =
60

The first to note is that the MEX file must be compiled like any other C code. This done within MATLAB using the command mex. In Linux, the output is a file with the extension mexglx. MATLAB's helpdesk can assist you if it is necessary. Go ahead and try now this example for your self.

The code for the dot product example is very easy to understand.

#include "mex.h"

void xdotyMex(double *x,double *y,double *z,int ColLen)
{
int j;
z[0] = 0;
for(j=0;j<j++){z[0] = z[0] + x[j]*y[j];}
}

void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[] )
{
double *x,*y, *z;
int ColLen;

if(nrhs!=2) {
mexErrMsgTxt("Two inputs required.");
} else if(nlhs>1) {
mexErrMsgTxt("Too many output arguments");
}
plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);

x = mxGetPr(prhs[0]);
y = mxGetPr(prhs[1]);
z = mxGetPr(plhs[0]);

ColLen = mxGetN(prhs[0]); /*M-Rows N-Columns*/

xdotyMex(x,y,z,ColLen);
}

The function xdotyMex is the dot product operation. The mexFunction has the two vector inputs. Thus, nrhs=2 should be true if you have entered the correct number of vectors in your call to the function within MATLAB. These vectors are stored in the pointer for the double precision variables x and y. To get input data mapped to x and y I use the mx* function mxGetPr. The output is pointed to by z, which because it is generated in C must be created with the command plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);. Finally, I use mxGetN to get the length of the vectors.

The previous example is a standard. One which I have written and is perhaps more interesting is found in the file RealTridiagSolverMex.c. This uses the Thomas algorithm to invert a tridiagonal matrix. This script is particular interesting because it demonstrates the need for caution when translating from MATLAB to C. In the following example, one sees that the super and sub-diagonals must be shifted when going from MATLAB which indexes starting at 1 to C which begins with 0.

>> mex -g RealTridiagSolverMex.c
>> sub = [6 7 0]';
>> sup = [0 4 5]';
>> diag = [1 2 3]';
>> A = spdiags([sub diag sup],-1:1,3,3);
>> full(A)
ans =
1 4 0
6 2 5
0 7 3
>> Bvector = [8 9 10]';
>> A\Bvector
ans =
1.3861
1.6535
-0.5248
>> subc = [0 6 7]';
>> supc = [4 5 0]';
>> diagc= [1 2 3]';
>> RealTridiagSolverMex(Bvector,subc,diagc,supc)
Number of Rows = 3 Columns = 1
ans =
1.3861
1.6535
-0.5248

The last example of a MEX function that I can share is provided in LagClenshawMEX.c. The corresponding MATLAB implementation of the program is given in LagClenshawAlgorith.m. A test case comparing the speed of the codes is given in LagClenshawTest.m This example is particularly interesting because it deals with complex variables. Originally C did not include an inherent complex variable. Fortunately with the updates in C99 a complex data type has been included but I have found that MATLAB's choice of C compiler does not adhere to the C99 conventions and thus does not include complex variables. It is possible to specify the compiler that MATLAB uses for the MEX file however this a topic which I have not been successful with. Instead, I have chosen to simply hard code the real and imaginary procedures in the C MEX code.

This LagClenshawAlgorithm.m and corresponding C codes compute the sum

f(t) = e(σ-b)tΣ an Ln(2bt)

In our case the coefficients an are complex vectors which are formed from the product of a matrix and a vector. The direction computation of the Laguerre polynomials Ln(2bt) and subsequent summation is a highly unstable process. The Clenshaw algorithm is a numerically stable procedure for the summation. It is described in detail in the website Mathworld Clenshaw.

Go ahead now and run the C and MATLAB codes by typing at the prompt LagClenshawTest.m. The coefficients in test run are random values. However, by selecting the seed for the rand number generator with the command rand('seed',0); I generate the same "random" numbers with run of the test file. A typical run generates data like this


Setting things up... 

Matrix and Vector Set up time 
elapsed_time = 
    0.0039 

Coefficient Matrix Set up Time 
elapsed_time = 
   9.2600e-04 

Matlab Script 
elapsed_time = 
    0.0148 

C MEX Code 
elapsed_time = 
    0.0152 

Maximum Absolute Element Difference 
ans = 
   1.2313e-13 

Maximum Relative Element Difference 
ans = 
   1.1370e-14 

Surprisingly, I have found that the C code and the MATLAB semi-vectorized script perform at nearly the same speed. Also, there are some variations from run to run in the computation times of the algorithms.
[Note: this seems to be true only for small size matrices/vectors. For large matrices/vectors the C code outperforms the Matlab script by about a factor of 5.]


Conclusion

MATLAB has a incredible diversity of rather obscure but potentially useful features. In this webpage, I have only attempted to illustrate, primarily through examples, how to use GUIs, dialog boxes, and MEX files. I only hope that these will be of use to you in your own endeavors with MATLAB.

Patrick Kano / 15 February 2004
http://math.arizona.edu/~swig/documentation/matlab-tips/index.php
Last modified: Tue, 06 Aug 2013 11:52:56 -0600
E-mail: swig@math.arizona.edu
Valid XHTML 1.0! Valid CSS!