LAB 12, 04/23/14 ________________ 1. User-defined functions in MATLAB share the prototype, syntax and M-file format of built-in functions. We saw examples of such functions with different numbers of input and output arguments, and where each function involved the execution of several commands. MATLAB also allows users to create so-called anonymous functions by means of a single command - on the fly, so to speak. Once created, an anonymous function can be used for the remainder of the session, but cannot be saved as a function M-file (it can however be saved/ reloaded using the SAVE command, or as part of a larger script file). Anonymous functions are a rather recent - and quite powerful - feature in MATLAB. 2. Suppose that we need to evaluate the expression % exp(-x).*cos(4*x-pi/3) several times during a session, and for different values of x. Instead of creating a function M-file (with one input and one output argument), we can simply type the command fun1 = @(x) exp(-x).*cos(4*x-pi/3) This creates an anonymous function with one input argument that evaluates the expression exp(-x).*cos(4*x-pi/3) for x equal to that argument. For example, fun1(0) fun1(0:0.1:1) plot(fun1(0:0.01:5)) A function with two input arguments would be fun2 = @(x,y) (cos((x+y-1)*pi/2)).^6 The input arguments are enclosed in @( ), separated with commas. The expressions can also involve previously defined constants, e.g., a = 1; b = 4; c = -pi/3; fun3 = @(x) exp(-a*x).*cos(b*x+c); If a, b and c change values later on, those changes will *not* be reflected in fun3. Thus fun3 will always have the same result as fun1. 3. The notation @ is associated with the concept of a function handle, which can be tricky at first. An anonymous function can be invoked in exactly the same way as built-in function, e.g., fun1(-0.5) but it also acts as function handle, i.e., it can serve as an input argument to a function that accepts other functions as inputs. This can be confusing, and is best explained by means of an example. 4. Suppose that we wish to compute the maximum value achieved by a function R-->R over a fixed discrete interval, say -1:0.0001:1 ; then repeat the computation for different functions. Thus the interval -1:0.0001:1 remains fixed, while the function F can vary. Two ways of doing this efficiently are: - using a function M-file (max1.m) %%%%%%%%%%%%%%%%%%%%%%%%%% function y = max1(F) y = max(F(-1:0.0001:1)) ; %%%%%%%%%%%%%%%%%%%%%%%%%% - using an anonymous function defined by max2 = @(F) max(F(-1:0.0001:1)) Either way, the argument F is a function. MATLAB requires use of a function handle in both cases. Thus if we want to compute the maximum of the cosine function over the given interval, we must use max2(@cos) If we use max2(cos) instead, we get an error. The same syntax is needed in using - the function max1.m instead of the anonymous max2; or - any other valid built-in or user-defined .m function instead of COS. On the other hand, if instead of the cosine function, we would like to maximize the value of the expression in the anonymous function fun1 (see above), we don't need a handle - since fun1 is already a handle. Thus we type max2(fun1) Typing max2(@fun1) on the other hand, produces an error. [Note: Before the introduction of function handles, evaluating a function having another function as an input argument was typically accomplished using the function FEVAL, where the function argument appeared as a string (i.e., 'function_name'). Function handles simplified this task considerably. Anonymous functions overshadowed another tool for defining functions on the fly, namely the inline function (which we don't discuss at all).] 5. Real-valued functions of two variables (i.e., R^2-->R) are typically evaluated on a discrete rectangular grid, i.e., AxB, where A and B are vectors of values of x and y, respectively. The result is a matrix of values of the function at the corresponding grid points. The function MESHGRID facilitates this computation by producing two separate matrices, one for the x-coordinates and another for the y-coordinates of the grid points. Thus for example, a = [-1:1:3] ; b = [0:0.2:1] ; [X,Y] = meshgrid(a,b) ; X % varies horizontally, not vertically Y % varies vertically, not horizontally Assuming that the expression for the function that we wish to evaluate is array-friendly, using X and Y instead of scalar variables will produce the matrix of values of the function over the rectangular coordinate grid. For example X.*Y % values of the expression x*y (Note that the matrices X and Y can be also obtained from ones(length(b),1)*a and b.'*ones(1,length(a)) - MESHGRID is faster!) A quick way of generating uniformly spaced intervals is though LINSPACE: % LINSPACE(L,R) : 100 points from L to R inclusive % LINSPACE(L,R,N) : N points from L to R inclusive 6. We have used grayscale images to represent the variation of functions of two variables over rectangular grids. For example, fun2 % recall definition of fun2 a = linspace(0,1) ; [X,Y] = meshgrid(a,a) ; Z = fun2(X,Y) ; imshow(Z,[]) A contour plot consists of a number of lines on the x-y grid over which the a function takes constant value; it thus depicts the variation of function in discrete terms. The simplest contour plot is produced by CONTOUR: contour(Z) % axes labeled by indices contour(X,Y,Z) % actual coordinates Note that the ridge formed by the straight-line contours has a different orientation that the one obtained by IMSHOW. This is because image coordinates have their origin (index (1,1)) at the top left corner of the image; this is known as the "matrix" axis mode, and is enforced using axis ij The default axis origin for all 2-D plots including CONTOUR is at the bottom left corner; this is nown as the "Cartesian" axis mode, and is enforced using axis xy (Keep the figure window open and try both commands.) A color-filled contour plot is obtained using contourf(Z) Different coloring schemes can be used, e.g., colormap summer colormap gray colormap jet The number of levels (lines), level values in contour plots can be varied (see HELP). 7. MATLAB has extensive 3-D plotting capabilities that are too many to list. The most useful plots are produced by % MESH 3-D wire-frame surface % SURF 3-D surface, basically a patched-up (filled) mesh and their variants. Try mesh(X,Y,Z) surf(X,Y,Z) shading flat % mesh lines removed surfc(X,Y,Z) xlabel('x'), ylabel('y') SURFC adds a 2-D contour plot on the bottom x-y plane. The presence of contours parallel to the line x+y=1 on the far side of the origin is a reminder that the surface continues beyond the ridge of height z=1 along x+y=1. It is not visible due to the default viewing angle, which can be changed using the VIEW command, or directly in the figure window (note the Rotate 3D icon on the toolbar). The VIEW command takes the form % VIEW(AZIMUTH, ELEVATION) where AZIMUTH and ELEVATION represent (respectively) horizontal and vertical rotations of an observer facing the origin from an initial position on the far negative y-axis. Both are quoted in degrees. view(3) % default 3D view, az.= -37.5, el. = 30 view(0,30) view(75,30) view(75,60)