Archive for April, 2009

Button customization

Friday, April 24th, 2009

Matlab’s button uicontrols (pushbutton and togglebutton) are basically wrappers for a Java Swing JButton object.

This will be the first in a series of posts showing how Matlab uicontrols can be customized in ways that you may never have thought possible.

Probably the simplest undocumented customization is the control’s acceptance of HTML and CSS Strings:

tooltip = '<html>HTML-aware<br><b>tooltips</b><br><i>supported';
labelTop= '<HTML><center><FONT color="red">Hello</Font> <b>world</b>';
labelBot=['<div style="font-family:impact;color:green"><i>What a</i>'...
          ' <Font color="blue" face="Comic Sans MS">nice day!'];
set(hButton, 'tooltip',tooltip, 'string',[labelTop '<br>' labelBot]);

Button with HTML label and tooltip

Button with HTML label and tooltip

For more powerful customization, we need to access the control’s underlying JList object. We do this by using my FindJObj submission on the File Exchange:

>> jButton = java(findjobj(hButton))
jButton =
com.mathworks.hg.peer.PushButtonPeer$1[,0,0,...]

Now that we have the jButton Java object reference, we can use get and set just like any Matlab handle. To see the list of all available properties, methods and callbacks, we can use my UIINSPECT submission on the File Exchange, or use Matlab’s built-in methodsview function.

This post is too short to present all the numerous ways in which the control can be customized with the Java properties and methods. Let’s list some of the more interesting properties:

  • Border – specified the border frame around the button, which is responsible for its 3D appearance. It can be modified to anything from a simple colored borderline to a recurring icon-pattern, as shown here. If set to [] then the button achieves a flat appearance, which can be useful for displaying click-able labels. For example, the blog hyperlink at the bottom of the FindJObj window is a simple button with no border, an HTML label and a callback that opens this blog webpage using the built-in web function:
    Button appearing as a hyperlink label

    Button appearing as a hyperlink label

  • Cursor – this can be used to set a control-specific cursor. For example, in the hyperlink button above, the cursor was set to: java.awt.Cursor(java.awt.Cursor.HAND_CURSOR). In another post I’ll show how to set a custom cursor, like the following Matlab icon:
    Custom cursor

    Custom cursor

  • DisplayedMnemonicIndex – (default=-1) indicates the character position within the text label where the Mnemonic (i.e, keyboard shortcut) should be displayed. Associated property Mnemonic (default=0) indicates the ASCII code of the mnemonic. In the following case, DisplayedMnemonicIndex=3 (remember that Java indices start at 0) and Mnemonic=73 (=’r'):
    Button With mnemonic

    Button With mnemonic

  • Margin, VerticalAlignment, HorizontalAlignment – these properties enable setting the label contents with respect to its borders. For example:
    Top-left with 8-pixel top margin

    Top-left with 8-pixel top margin

  • Icon, DisabledIcon, DisabledSelectedIcon, PressedIcon, RolloverIcon, RolloverSelectedIcon, SelectedIcon – these icons may be set to present a different appearance depending on component state. Associated property IconTextGap (default=4) determines the gap in pixels between the icon and the button text label. Associated properties HorizontalTextPosition and VerticalTextPosition specify the label text’s alignment relative to the label icon. These two properties accept the same SwingConstants values as HorizontalAlignment and VerticalAlignment above. For example, let’s display an icon to the right and upward of the text:
    
    myIcon = fullfile(matlabroot,'/toolbox/matlab/icons/warning.gif');
    jButton.setIcon(javax.swing.ImageIcon(myIcon));
    jButton.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
    jButton.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
    

    Button with text and icon

    Button with text and icon

  • MultiClickThreshhold – (default=0) sets the number of milliseconds between subsequent processed user mouse clicks on the button. Any clicks that occur within the specified number (e.g., fast double-clicks) will be considered by the component as only a single click. The default value of 0 means that all clicks will be processed separately, which is often undesirable in GUI applications. Remember that the value is in milliseconds, not seconds.
  • FlyOverAppearance – boolean flag (default=false); if set, the button appearance is changed to a flat (2D) appearance with a special 3D border effect displayed on mouse hover. This appearance is useful for toolbar buttons, and is an extension by Matlab’s button implementation (does not exist in the standard Swing class).

There are quite a few other useful properties, methods (for example, jButton.doClick() to programmatically click a button) and even some 30 callbacks, detailed in a separate post. The list above is by no way comprehensive – I hope it whet your appetites for exploration using FindJObj and UIINSPECT – it’s a fun ride and the GUI rewards are worth the effort!

Please let me know of any nice customizations in your Matlab applications. Leave a comment below or drop me an email.

Spy Easter egg

Saturday, April 11th, 2009

For the 2009 Easter holiday, I thought I’d post a Matlab Easter egg, which I found on http://www.eeggs.com/items/47352.html: spy is a built-in stock Matlab function for visualizing sparse matrices. If you run spy with no input arguments, it uses an undocumented default built-in sparse matrix that generates one of the spies in the famous Spy vs. Spy comics series:

spy;

Matlab spy Easter egg

ismembc – undocumented helper function

Wednesday, April 8th, 2009

Matlab has a variety of internal helper functions which are used by the main (documented) functions. Some of these helper functions are undocumented and unsupported, but may be helpful in their own right – not just as internal support functions.

In this post I want to present Matlab’s built-in ismembc helper function. This function is used within the stock Matlab ismember and setxor functions for fast processing of the core ismember functionality in “regular” cases: arrays of sorted, non-sparse, non-NaN data in which we’re only interested in the logical membership information (not the index locations of the found members). In such cases, ismembc can be used directly, saving ismember’s sanity-checks overhead. ismembc uses the same interface (two inputs, single logical output) as ismember and can be a drop-in replacement for ismember for these “regular” cases.

The performance improvement may be significant: In a recent post, MathWorks’ Loren Shure presented different approaches for fast data retrieval, highlighting the ismember function. Let’s compare:

>> % Initial setup
>> n=2e6; a=ceil(n*rand(n,1)); b=ceil(n*rand(n,1));

>> % Run ismember several times, to rule-out JIT compilation overheads
>> tic;ismember(a,b);toc;
Elapsed time is 2.882907 seconds.
>> tic;ismember(a,b);toc;
Elapsed time is 2.818318 seconds.
>> tic;ismember(a,b);toc;
Elapsed time is 3.005967 seconds.

>> % Now use ismembc:
>> tic;ismembc(a,b);toc;
Elapsed time is 0.162108 seconds.
>> tic;ismembc(a,b);toc;
Elapsed time is 0.204108 seconds.
>> tic;ismembc(a,b);toc;
Elapsed time is 0.156963 seconds.

ismembc is actually a MEX file (%matlabroot%\toolbox\matlab\ops\ismembc.mexw32). Its source code is included in the same folder (%matlabroot%\toolbox\matlab\ops\ismembc.cpp) and is actually very readable. From the source code comments we learn that the comment in setxor about ismembc usage is misleading: that comment stated that the inputs must be real, but the source-code indicates that imaginary numbers are also accepted and that only the real-part should be sorted.

ismembc should not be used carelessly: as noted, its inputs must be sorted non-sparse non-NaN values. In the general case we should either ensure this programmatically (as done in setxor) or use ismember, which handles this for us.

The nice thing about ismembc is that its source code (ismembc.cpp) is included, so even if future Matlab releases stop using this function, you can always mex-compile the source code and use it.

Readers interested in ismembc might also be interested in its sibling help function, ismembc2, which is also a mex file located (with source-code) in the same folder as ismembc. Whereas ismembc returns an array of logical values, ismembc2 returns the index locations of the found members.

Undocumented profiler options

Thursday, April 2nd, 2009

The Matlab profiler is a powerful tool for debugging performance-related issues in Matlab applications. However, it also has some undocumented options that facilitate other forms of debugging, namely memory bottlenecks and JIT (Just-In-Time compilation) problems.

To turn on memory stats in the profile report, run this (only once is necessary – will be remembered for future profiling runs):

profile -memory on;
profile('-memory','on');  % an alternative

To turn on JIT information, run this (again, only once is necessary, prior to profile report):

setpref('profiler','showJitLines',1);

You will then see additional JIT and memory (allocated, freed and peak) information displayed in the profile report, as well as the options to sort by allocated, freed and peak memory:


Profile report with memory & JIT infoProfile report with memory & JIT info

Profile report with memory & JIT info

Profile report with memory & JIT info

For those interested, the references to these two options appear within the code of profview.m (line 1199 on R2007b), for the JIT option:

showJitLines = getpref('profiler','showJitLines',false);

…and profile.m (lines 163-165 on R2007b), for the memory option:

if memory ~= -1
    callstats('memory', memory);
end

Note that there appears to be two undocumented additional memory-related options in profile.m (lines 311-312):

options = {'detail', 'timer', 'history', 'nohistory', 'historysize', ...
           'timestamp', 'memory', 'callmemory', 'nomemory' };

However, ‘-nomemory’ appears to simply turn the memory stats collection off, and ‘-callmemory’ is not recognized because of a bug in line 349, which looks for ‘callnomemory’…:

    case 'callnomemory'   % should be 'callmemory'
           memory = 2;

When this bug is fixed, we see that we get only partial memory information, so the ‘-callmemory’ option is really not useful – use ‘-memory’ instead.