BlinkDagger - the end?

July 8th, 2009

In his latest post on BlinkDagger, Quan Quach announced that the BlinkDagger blog will be frozen following co-author Daniel Sutoyo’s hiring by The MathWorks and the continuous strain of maintaining the blog single-handedly.

This is sad news indeed for the Matlab user community. Over the past few years, BlinkDagger has become the largest independent Matlab-related blog (at least that I know of), with some 150 well-written tutorials on a very wide variety of Matlab-related topics. In fact, I believe that only the official Matlab blogs and the Matlab CSSM forum contain more Matlab content. Although there are reportedly over a million Matlab users worldwide, there is precious little independent online Matlab content. Perhaps the need is answered by CSSM and the official blogs, and perhaps the reason is other. In any case, BlinkDagger’s retirement will be well-felt.

As a novice (4-month) blogger I can well appreciate the effort it took Quan and Daniel to write so much well-crafted content, follow-up on numerous comments and continuously think of interesting article ideas. The fact they have succeeded in doing so consistently for so long, without noticeable quality degradation, is remarkable. So, while regretting their action, I can certainly understand it. I truly wish both Quan and Daniel the best of luck in their new adventures, and send them an enormous hug of gratitude for their services to the Matlab community.

Don’t be lazy - be a sport - visit the BlinkDagger link and tell Quan and Daniel that you too appreciate their efforts. Let them leave the stage with a standing ovation rather than a whimper. They deserve it.

Yair Altman

Bookmark and Share

EditorMacro - assign a keyboard macro in the Matlab editor

July 1st, 2009

Over the past years there have been quite a few requests to enable keyboard macros and keybinding modifications in the Matlab editor. Some posters have even noted this lack as their main reason to use an external editor. Coincidentally, some weeks ago I was approached by a reader (Grant Roch) to help with assigning some textual editor macros, and with joint work we were able to figure out a basic working mechanism. The latest user comment on this issue was posted on the official Matlab Desktop blog yesterday. All this prompted me to finally post a solution to this need: My EditorMacro utility is now available for download on the Mathworks File Exchange. In this post I will detail some of its inner workings, which rely on undocumented Matlab features.

In a nutshell, EditorMacro sets the KeyPressedCallback property (explained in a previous post) for each of the editor’s document panes, to an internal function. This internal function then checks each keystroke against a list of registered keybindings. The list itself is persisted in the editor object’s hidden ApplicationData property (accessible via the getappdata/setappdata built-in functions). If a match is found, then the associated macro is invoked. Depending on the macro type, some text can be inserted at the current editor caret position, or replacing the selected editor text, or a non-text Matlab function/command can be invoked.

This enables EditorMacro to be used for quickly inserting code templates (header comments, try-catch blocks etc.) or for automating Matlab unit testing.

Here’s a typical usage example: start by defining a simple function that returns a dynamic header comment:

function comment = createHeaderComment(hDocument, eventData)
  timestamp = datestr(now);
  username = getenv('username');
  %computer = getenv('computername');  % unused
  lineStr = repmat('%',1,35);
  comment = sprintf(...
      ['%s\n' ...
       '%% \n' ...
       '%% Name:    functionName\n' ...
       '%% \n' ...
       '%% Desc:    enter description here\n' ...
       '%% \n' ...
       '%% Inputs:  enter inputs here\n' ...
       '%% \n' ...
       '%% Outputs: enter outputs here\n' ...
       '%% \n' ...
       '%% Created: %s\n' ...
       '%% \n' ...
       '%% Author:  %s\n' ...
       '%% \n' ...
       '%s\n'], ...
       lineStr, timestamp, username, lineStr);
end  % createHeaderComment

Now define a macro to use this function, and another simple try-catch template macro:

>> EditorMacro('Alt-Control-h', @createHeaderComment);
>> macroStr = 'try\n  % Main code here\ncatch\n  % Exception handling here\nend';
>> b = EditorMacro('Ctrl alt T', macroStr)
b = 
    'ctrl alt pressed H'    @createHeaderComment    'text'
    'ctrl alt pressed T'             [1x60 char]    'text'

Now start with a blank document and click <Ctrl>-<Alt>-H and <Ctrl>-<Alt>-T. This is the end result:

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
% Name:    functionName
% 
% Desc:    enter description here
% 
% Inputs:  enter inputs here
% 
% Outputs: enter outputs here
% 
% Created: 01-Jul-2009 23:31:46
% 
% Author:  Yair Altman
% 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
try
  % Main code here
catch
  % Exception handling here
end

Keybindings are normalized using Java’s built-in javax.swing.KeyStroke.getKeyStroke() method, to enable the user a very wide range of keystroke naming formats (e.g., ‘Alt-Control-T’ or ‘ctrl alt t’).

I have taken great pains to make EditorMacro compatible with all Matlab versions since 6.0 (R12). This was no easy feat: Matlab 7 made some significant changes to the editor layout. Luckily, once I found out how to get a handle to the Matlab 6 editor object (this took some hours of trial-and-error), listing its display hierarchy was simple and the modifications were generally straight-forward, although non-trivial (different quirks due to missing default type-castings, missing eventData in invoked callbacks etc…). Please feel free to look at EditorMacro’s source code for the clearly-marked Matlab 6 segments.

For the record, here is a snippet showing how to get the editor object in Matlab 6 and 7. Note that the desktop handle is only useful to get the editor handle in Matlab 6 - we need a totally different way in Matlab 6:

try
   % Matlab 7
   jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
   jEditor = jDesktop.getGroupContainer('Editor');
catch
   % Matlab 6
   try
      %desktop = com.mathworks.ide.desktop.MLDesktop.getMLDesktop;
      % no use: can't get to the editor from the desktop handle in Matlab 6...
      openDocs = com.mathworks.ide.editor.EditorApplication.getOpenDocuments;
      firstDoc = openDocs.elementAt(0);
      jEditor = firstDoc.getParent.getParent.getParent;
   catch
      error('Cannot find Matlab editor handle: possibly no open documents');
   end
end

Another complication arose due to the different layout used for floating/maximized/tiled document layout in the editor. Yet another was due to the different behavior (at least on Matlab 6) between a one-document and a multi-document editor view.

Due to the way keyboard events are processed by the Matlab editor, KeyPressedCallback needs to be set separately for all the open document panes and split-panes. Since we also wish newly-opened documents to recognize the macro bindings, we need to set the common container ancestor’s ComponentAddedCallback to an internal function that will handle the KeyPressedCallback instrumentation for each newly-opened document. Again, this needs to be done somewhat differently for Matlab 6/7.

Note that EditorMacro relies on the editor’s internal display layout, which is very sensitive to modification between Matlab releases (as it has between Matlab 6 and 7, for example).

All-in-all, I believe EditorMacro provides a useful and long-awaited service, which should in fact be part of the built-in editor.

Bookmark and Share

Setting the Matlab desktop layout programmatically

June 24th, 2009

The Matlab desktop enable users to switch between different presentation layouts of the desktop panels (Command Window, Workspace etc.). This has been supported as far back as Matlab 6 (R12), with newer Matlab releases adding improved functionality such as the ability to save user-defined layouts, as Kristin explained in the official Matlab desktop blog.

The only supported way to save and switch layouts is to use the desktop’s main menu. Since Kristin has posted her write-up, a few people have posted unanswered follow-up comments requesting to know how to programmatically save and switch layouts. I will now show how this can be done.

First, we need to get the Java handle of the Matlab desktop. We can then investigate this handle using the built-in methodsview function or my UIInspect utility on the File Exchange. We quickly see the relevant layout-related functions, which we can put to good use:

% Get the desktop's Java handle (Matlab 7 only)
desktop = com.mathworks.mde.desk.MLDesktop.getInstance;
 
% Inspect the available desktop functions
methodsview(desktop);
uiinspect(desktop);
 
% Save the current layout
desktop.saveLayout('Yair');
 
% Switch between different layouts
desktop.restoreLayout('Yair');
desktop.restoreLayout('Default');
desktop.restoreLayout('History and Command Window');

Desktop layout menu in Matlab 7

Desktop layout menu in Matlab 7

Note that trying to restore an invalid layout name simply does nothing (does not throw an error).

Also note that this relies heavily on unsupported and undocumented internal implementation, which may change without prior notice between Matlab releases. The code snippet above works on several Matlab 7 releases. But for Matlab 6.0 (R12), for example, it needs to be modified:

% Get the desktop's Java handle (Matlab 6 only)
desktop = com.mathworks.ide.desktop.MLDesktop.getMLDesktop;
 
% Inspect the available desktop functions
% Note: in Matlab 6, methodsview() did not accept object handles
methodsview('com.mathworks.ide.desktop.MLDesktop');
%uiinspect(desktop);  % UIINSPECT does not work on Matlab 6
 
% Save the current layout
% saving the desktop is not possible in Matlab 6
 
% Switch between different layouts
desktop.set5PanelLayout;
desktop.setTallLayout;
desktop.setShortLayout;
desktop.setDefaultDesktop;
desktop.setMolerMode;        % ='Command window only'

Desktop layout menu in Matlab 6

Desktop layout menu in Matlab 6

Note that Matlab 6 did not have a generic restoreLayout() function, instead using a few pre-defined setXXX(). Also note that Matlab 6 did not have the saveLayout() function (it did have saveDesktop(string,string) and restoreDesktop(string,string), which I leave as an excercise to readers).

This has been the first example of many useful things that can be done with the Matlab desktop handle. In the future I will describe other aspects. Perhaps the main lesson to be learned from this post is that essentially anything that can be done via the menu can also be done programmatically.

Bookmark and Share

Changing system preferences programmatically

June 17th, 2009

My very first post on this blog showed how to change Matlab’s command-window colors. In that post I promised to write another post detailing how system preferences can be changed from the command line.

Last week I wrote about undocumented GUIDE features. After my initial post, I realized that I forgot to mention all the different relevant system preferences that can also be modified. I therefore modified last week’s post with the preferences information. I now wish to finally detail how such preferences can be changed programmatically, from within your Matlab application or from the Matlab desktop command prompt.

Matlab’s user preferences are stored in the matlab.prf text file which is stored in the user’s Matlab preferences folder:

edit(fullfile(prefdir,'matlab.prf'));

Each preference appears to be on a separate line in the following format: <pref-name>=<pref-type><pref-value>

where <pref-type> appears to be one of these:

  • ‘B’ => boolean/logical flag
  • ‘C’ => color (RGB numeric value)
  • ‘F’ => font (type,size,name)
  • ‘I’ => int16
  • ‘J’ => int64
  • ‘R’ => rectangular area (x,y,h,w)
  • ‘S’ => string/char

Examples:
    EditorShowLineNumbers=Btrue
    EditorMaxCommentWidth=I120

You can read the preference names from this matlab.prf file and then use the following (you-guessed-it) java calls to get/set the values:

com.mathworks.services.Prefs.get<type>Pref(<pref-name>)
com.mathworks.services.Prefs.set<type>Pref(<pref-name>, newValue);

where <type> is one of: Boolean, Color, RGBColor, Font, Integer, Rectangle, String, Double (I believe Doubles get converted to int64 - possibly a bitwise casting since both use 64 bits)

For example:

com.mathworks.services.Prefs.getBooleanPref('LayoutSnapToGrid')
com.mathworks.services.Prefs.setIntegerPref('LayoutGridWidth', 25)

adding a second argument to get<type>Pref() appears to indicate a default value that is returned if <pref-name> is not defined:

com.mathworks.services.Prefs.getIntegerPref('xxxx',123)
=> 123

We can programmatically set any preference key we like - we are not limited to Matlab’s built-in set. I used this feature in my CPRINTF utility, to set user-defined colors for later use by the desktop’s UI syntax-highlighting engine. The relevant code segment is this:

% Convert a Matlab RGB vector into a known style name (e.g., '[255,37,0]')
function styleName = getColorStyle(rgb)
 
  % Convert Matlab RGB array into a Java Color object
  intColor = int32(rgb*255);
  javaColor = java.awt.Color(intColor(1), intColor(2), intColor(3));
 
  % Preference key name format: '[RRR,GGG,BBB]'
  styleName = sprintf('[%d,%d,%d]',intColor);
 
  % Set/update the preference with this Java Color
  com.mathworks.services.Prefs.setColorPref(styleName,javaColor);

…which in turn adds entries such as the following to my matlab.prf file:
    [12,34,67]=C-15982013

Note that -15982013 = 0xFF0C2243, which is the RGB value [12,34,67] with an opaque alpha value. This value can later be retrieved using:

>> com.mathworks.services.Prefs.getColorPref('[12,34,67]')
ans =
java.awt.Color[r=12,g=34,b=67]

Warning: I published much of this information on the CSSM forum back in 2007. Ben Steiner then shared his experience on that thread that:

For anyone else that’s playing with this: I don’t advise trying to edit the matlab.prf via matlab(!). I created a situation that made Matlab unworkable. I did find that deleting the matlab.prf completely (in frustration) solved it.

Take a look at your matlab.prf file - can you spot any interesting preference? If so, please share it in the comments section below.

Bookmark and Share

GUIDE customization

June 10th, 2009

GUIDE is the acronym for Matlab’s Graphical User Interface Design Editor. It is very handy for designing simple GUI figures, although my experience has shown that it has limitations for complex GUIs. Nevertheless, GUIDE is the tool used by most Matlab developers when designing GUIs. In this post, I will show a few undocumented customizations that could help make GUIDE sessions more productive.

The starting point is GUIDE’s undocumented return value, which is a Java reference to the Layout Editor panel within the GUIDE figure frame:

>> h = guide
h =
Layout Document [untitled]

>> h.getClass
ans =
class com.mathworks.toolbox.matlab.guide.LayoutEditor

This return handle can be used to access GUIDE components and functionality. We can start by inspecting the interesting GUIDE layout hierarchy using my FindJObj utility, and the associated properties and method using my UIInspect utility:

>> h.findjobj;
>> h.uiinspect;

Hierarchy of Layout Editor within the GUIDE frame

Hierarchy of Layout Editor within the GUIDE frame

Note: If you wish to see the hierarchy of the entire GUIDE figure frame, simply run FindJObj on the frame reference, by either of the two following methods (and similarly for UIInspect):

>> findjobj(h.getFrame);
>> findjobj(h.getTopLevelWindow);

We see that the Layout Editor contains, in addition to the expected LayoutArea and two MWScrollbars, several objects that relate to a ruler. These rulers can be activated via the GUIDE menu (Tools / Grid and Rulers), or via the Matlab Command Prompt as described below:

Looking at the ruler properties in FindJObj or UIInspect, we can see a settable boolean property called “RulerState”. If we turn it on we can see that a very handy pixels-ruler appears. Once we set this property, it remains in effect for every future GUIDE session:

Before: GUIDE with no rulers

Before: GUIDE with no rulers

h.getComponent(0).getComponent(4).setRulerState(true);  % Horizontal
h.getComponent(0).getComponent(5).setRulerState(true);  % Vertical

Note: RulerState actually controls a system preference (LayoutShowRulers, a boolean flag) that controls the visibility of both rulers, and persists across Matlab/GUIDE sessions. To change the visibility of only a single ruler for this GUIDE session only, or on old Matlab versions (e.g. Matlab 7.1 aka R14 SP3) that do not have the ‘RulerState’ property, use the hide()/show()/setVisible(flag) methods, or set the ‘Visible’ property:

% Equivalent ways to show horizontal ruler for this GUIDE session only
hRuler = h.getComponent(0).getComponent(4);  % =top horizontal ruler
set(hRuler, 'Visible','on');
hRuler.setVisible(true);  % or: hRuler.setVisible(1)
hRuler.show();

After: GUIDE with pixel rulers

After: GUIDE with pixel rulers

Using this method, we can customize the rulers - options which are unavailable using the standard GUIDE menu options: We can specify horizontal/vertical grid size, tick & label interval and similar ruler properties. For example, let’s set a 5-pixel minor tick interval, 25-pixel major interval, labels every 50 pixels, starting offset of 40 pixels and a ruler size limited at 260 pixels:

hRuler = h.getComponent(0).getComponent(4);  % =top horizontal ruler
set(hRuler, 'MinorInterval',5, 'MajorInterval',25);
set(hRuler, 'LabelInterval',50, 'LabelUnit',50);
set(hRuler, 'Margin',40, 'Length',260);

GUIDE with modified pixel rulers

GUIDE with modified pixel rulers

Note that the vertical ruler’s labels start (=LabelStart property) at the figure’s height, and have a decreasing LabelInterval of -50. This is done because Java coordinates start counting from the top-left corner downward, whereas Matlab counts from the bottom-left upward. In GUIDE, we naturally wish to display the Matlab coordinates, hence the transformation.

Note: unfortunately, most of these properties do not have equivalent settable system properties that I could find. Here is a list of all the GUIDE-related system properties that I found:

  • LayoutShowRulers - boolean, controls display of both rulers
  • LayoutShowGuides - boolean, controls display of blue guidelines
  • LayoutShowGrid - boolean, controls display of gray gridlines
  • LayoutGridWidth - integer, controls the size of the grid boxes
  • LayoutSnapToGrid - boolean, controls snap-to-grid behavior
  • LayoutActivate - boolean, controls ability to run (activate) unsaved figures without confirmation
  • LayoutChangeDefaultCallback - boolean, ??? (I can see this preference in my matlab.prf file but I have no idea what it does or how it got there…)
  • LayoutExport - boolean, controls ability to export unsaved figures without confirmation
  • LayoutExtension - boolean, controls display of file extension in the GUIDE window title
  • LayoutFullPath - boolean, controls display of file path in the GUIDE window title
  • LayoutMCodeComments - boolean, controls generation of comments for m-file callbacks
  • LayoutToolBar - boolean, controls display of the GUIDE widow toolbar
  • LayoutToolNames - boolean, controls display of tool names in the components palette

Have you discovered other undocumented features in GUIDE? If so, please share your findings in the comments section below.

Warning: These undocumented features are way deep in unsupported territory. They depend heavily on Matlab’s internal implementation, which may change without any prior notice between Matlab releases. They work ok on Matlab versions 7.1 (R14 SP3) through 7.6 (R2008a), and perhaps on other versions as well. However, the very next Matlab release might break these features, so beware.

Bookmark and Share

Legend ‘-DynamicLegend’ semi-documented feature

June 4th, 2009

In one of my projects, I had to build a GUI in which users could interactively add and remove plot lines from an axes. The problem was that the legend needed to be kept in constant sync with the currently-displayed plot lines. This can of course be done programmatically, but a much simpler solution was to use legend’s semi-documented ‘-DynamicLegend’ feature. Here’s a simple example:

x=0:.01:10;
plot(x, sin(x), 'DisplayName','sin');
legend('-DynamicLegend');
 
hold all;   % add new plot lines on top of previous ones
plot(x, cos(x), 'DisplayName','cos');

We can see how the dynamic legend automatically keeps in sync with its associated axes contents when plot lines are added/removed, even down to the zoom-box lines… The legend automatically uses the plot lines ‘DisplayName’ property where available, or a standard ‘line#’ nametag where not available:


Dynamic legend

Dynamic legend

DynamicLegend works by attaching a listener to the axes child addition/deletion callback (actually, it works on the scribe object, which is a large topic for several future posts). It is sometimes necessary to selectively disable the dynamic behavior. For example, in my GUI I needed to plot several event lines which looked alike, and so I only wanted the first line to be added to the legend. To temporarily disable the DynamicLegend listener, do the following:

% Try to disable this axes's legend plot-addition listener
legendAxListener = [];
try
   legendListeners = get(gca,'ScribeLegendListeners');
   legendAxListener = legendListeners.childadded;
   set(legendAxListener,'Enable','off');
catch
   % never mind...
end
 
% Update the axes - the legend will not be updated
...
 
% Re-enable the dynamic legend listener
set(legendAxListener,'Enable','on');

Unfortunately, this otherwise-useful DynamicLegend feature throws errors when zooming-in on bar or stairs graphs. This can be replicated by:

figure;
bar(magic(4));  %or: stairs(magic(3),magic(3));
legend('-DynamicLegend');
zoom on;
% Now zoom-in using the mouse to get the errors on the Command Window

The fix: modify %MATLABROOT%\toolbox\matlab\scribe\@scribe\@legend\init.m line #528 as follows:

%old:
str = [str(1:insertindex-1);{newstr};str(insertindex:length(str))];
 
%new:
if size(str,2)>size(str,1)
    str=[str(1:insertindex-1),{newstr},str(insertindex:length(str))];
else
    str=[str(1:insertindex-1);{newstr};str(insertindex:length(str))];
end

The origin of the bug is that bar and stairs generate hggroup plot-children, which saves the legend strings column-wise rather than the expected row-wise. My fix solves this, but I do not presume this solves all possible problems in all scenarios (please report if you find anything else).

The DynamicLegend feature is semi-documented. This means that the feature is explained in a comment within the function (which can be seen via the edit(‘legend’) command), that is nonetheless not part of the official help or doc sections. It is an unsupported feature originally intended only for internal Matlab use (which of course doesn’t mean we can’t use it). This feature has existed many releases back (Matlab 7.1 for sure, perhaps earlier), so while it may be discontinued in some future Matlab release, it did have a very long life span… The down side is that it is not supported: I reported the bar/stairs issue back in mid-2007 and so far this has not been addressed (perhaps it will never be). Even my reported workaround in January this year went unanswered (no hard feelings…).

DynamicLegend is a good example of a useful semi-documented feature. Some other examples, which I may cover in future posts, include text(…,’sc’), drawnow(‘discard’), several options in pan and datacursormode etc. etc.

There are also entire semi-documented functions: many of the uitools (e.g., uitree, uiundo), as well as hgfeval and others.

Have you discovered any useful semi-documented feature or function? If so, then please share your finding in the comments section below.

Bookmark and Share

Spicing up Matlab uicontrol tooltips

May 27th, 2009

Outside the official Matlab blogs, perhaps the most widely known Matlab-related active blog is BlinkDagger. This blog is certainly worth following, especially for novice Matlab users who could gain fresh angles on regular programming tasks that have a simple solution in Matlab.

In one of their latest posts, BlinkDagger described how to use tooltips in Matlab GUI. In one of this blog’s very first posts, I described how HTML can easily be used with Matlab uicontrols. Let’s now combine these ideas to show how HTML support can easily be used to spice-up the tooltips.

Let’s start with a simple styled multi-line tooltip:

str = '<html><b>line #1</b><br><i><font color="red">line#2';
set(hControl,'tooltipString',str);

Multi-line HTML'ed tooltip

Multi-line HTML'ed tooltip

This technique was used to display the informative tooltip for my Java-based data table utility on the Matlab file Exchange:

Multi-line HTML-styled tooltip

Multi-line HTML-styled tooltip

Tooltips can also be used to present images, using the HTML <img> tag. However, the image src (filename) needs to be formatted in a URL-compliant format such as ‘http://undocumentedmatlab.com/images/table.png‘ or ‘file:/C:\Yair\Undocumented Matlab\Images\table.png’.

If you try to use a non-URL-format filename, the image will not be displayed. Instead, a placeholder box will appear. For example, let’s take the table screenshot above and try to place its filename directly in the tooltip HTML:

filePath = 'C:\Yair\Undocumented Matlab\Images\table.png';
str = ['<html><center><img src="' filePath '"><br>' filePath];
set(hButton,'tooltipString',str);

Tooltip with invalid HTML img source URL

Tooltip with invalid HTML img source URL

If we fix filePath to be a valid URL, it now looks as intended:

filePath = 'C:\Yair\Undocumented Matlab\Images\table.png';
filePath = strrep(['file:/' filePath],'\','/');
str = ['<html><center><img src="' filePath '"><br>' ...
       '<b><font color="blue">' filePath];
set(hButton,'tooltipString',str);

Tooltip with HTML image and caption


Tooltip with HTML image and caption

Note that the tooltip looks enormous (it’s actually even downsized to fit this post…). This is because our HTML <img> was not limited in size and so the tooltip was created to display the screenshot in its original large size. In order to limit the tooltip size, simply add the height and width attributes to the HTML <img> tag, remembering to preserve the original image aspect ratio.

Now that we know the basics, we can really go wild with HTML and CSS formatting. Have you configured any kick-butt tooltip in your application? If so, please share it here.

Bookmark and Share

tic / toc - undocumented option

May 22nd, 2009

I have recently discussed undocumented features in Matlab’s built-in profiler. Another tool often used for ad-hoc performance profiling of Matlab code are the built-in duo functions tic and toc:

>> tic; magic(500); toc
Elapsed time is 0.474647 seconds.

Both tic and toc are documented functions, but they contain an undocumented option (at least until R2008b - see history below) that enables nested clocking. The problem that is solved using this undocumented option is that if we try to use tic/toc in external function parentFcn and also in the internal function childFcn, we get unexpected results. This happens because our childFcn’s invocation of tic has reset the clock and so parentFcn’s clock is now obviously incorrect:

function parentFcn
 
    % Start clocking
    tic;
 
    % Do something long...
    m1 = magic(1500);
 
    % Call nested function
    toc1 = childFcn;
 
    % Present clock timing
    toc2 = toc;
    fprintf('Elapsed time for childFcn:  %0.3f secs\n',toc1)
    fprintf('Elapsed time for parentFcn: %0.3f secs\n',toc2)
 
 
    % Nested function with separate clocking
    function t = childFcn
        tic;
        m = magic(800);
        t = toc;
    end  % childFcn
 
end  % parentFcn
>> parentFcn
Elapsed time for childFcn:  1.063 secs
Elapsed time for parentFcn: 1.068 secs

The solution: use a separate handle for each clock. The format is very simple:

>> t = tic;
>> toc(t)

This format ensures independent clocking of the clocks. Clockings can now be safely nested and even partial overlap is possible:

function parentFcn
 
    % Start clocking
    t1 = tic;
 
    % Do something long...
    m1 = magic(1500);
 
    % Call nested function
    toc1 = childFcn;
 
    % Present clock timing
    toc2 = toc(t1);
    fprintf('Elapsed time for childFcn:  %0.3f secs\n',toc1)
    fprintf('Elapsed time for parentFcn: %0.3f secs\n',toc2)
 
 
    % Nested function with separate clocking
    function t = childFcn
        tic;
        m = magic(800);
        t = toc;
    end  % childFcn
 
end  % parentFcn
>> parentFcn
Elapsed time for childFcn:  1.123 secs
Elapsed time for parentFcn: 4.992 secs

For the record, this undocumented option was first presented by the MathWorks support team as an official workaround for the aforementioned problem. The solution was originally posted for Matlab R2006b, but actually the option was supported by Matlab versions at least as early as R14SP3 (7.1) - perhaps even earlier (I don’t have ready access to earlier versions). I do know that it was not supported on release R12 aka 6.0, but I don’t know whether it was introduced in 6.5, 7.0 or 7.1. This option has only been documented since R2008b, although it has existed in many earlier releases.

Now here’s a puzzle for all you undoc fans out there: toc has a really undocumented option of using an uninitialized uint64 value, rather than an actual tic handle. It seems that whichever value is passed will always result in the same result, but this result is uncorrelated to any possible event (start of Matlab, midnight etc.). It even works without any prior tic invocation! I would love to hear your thoughts on what you think this strange toc result might represent:

>> toc(uint64(1))
Elapsed time is 72825.947547 seconds.
>> toc(uint64(1234))
Elapsed time is 72826.538296 seconds.
Bookmark and Share

cprintf - display formatted color text in the Command Window

May 13th, 2009

In earlier posts I showed how to modify the Command Window (CW) text and background color, and a very limited method of displaying red (error) and blue (hyperlinked) CW messages. Since then, I was obsessed with finding a better way to CW display text in any color. After lots of trial-and-errors, frustrations and blind alleys - many more than I imagined when I started out - I am now very proud to say that I have solved the problem. My cprintf utility is now available in the File Exchange.

Before I describe the internal implementation, let me show the end result:

cprintf - display styled formatted text in the Command Window

cprintf - display styled formatted text in the Command Window

cprintf relies on ideas presented in the previous two posts mentioned above. Since the CW is a JTextArea which does not enable style segments, I was curious to understand how Matlab is able to display syntax highlighting in it. This is probably done using a dedicated UI class (com.mathworks.mde.cmdwin.CmdWinSyntaxUI), as suggested in the second post. This is an internal Matlab Java class, so we cannot modify it. It seemed like a dead end for a while.

But what if we could fool the UI class to think that our text should be syntax highlighted? at least then we’d have a few more colors to play with (comments=green, strings=purple etc.). So I took a look at the CW’s Document component (that holds all text and style info) and there I saw that Matlab uses several custom attributes with the style and hyperlink information:

  • the SyntaxTokens attribute holds style color strings like ‘Colors_M_Strings’ for strings or ‘CWLink’ for hyperlinks
  • the LinkStartTokens attribute holds the segment start offsets for hyperlinks (-1 for non-hyperlinked, 0+ for hyperlink)
  • the HtmlLink attribute holds the URL target (java.lang.String object) for hyperlinks, or null ([]) for non-hyperlink.

I played a hunch and modified the style of a specific text segment and lo-and-behold, its CW color changed! Unfortunately, I found out that I can’t just fprintf(text) and then modify its style - for some unknown reason Matlab first needs to place the relevant segment in a “styled” mode (or something like this). I tried to fprintf(2,text) to set the red (error) style, but this did not help. But when I prepended a simple hyperlink space character I got what I wanted - I could now modify the subsequent text to any of the predefined syntax highlighting colors/styles.

But is it possible to use any user-defined colors, not just the predefined syntax highlighting colors? I then remembered my reported finding from the first post about CW colors that ‘Colors_M_Strings’ and friends are simply preference color objects that can be set using code like:

>> import com.mathworks.services.*;
>> Prefs.setColorPref('Colors_M_Strings',java.awt.Color(...));

So I played another hunch and tried to set a new custom preference:

>> Prefs.setColorPref('yair',java.awt.Color.green);
>> Prefs.getColorPref('yair')
ans =
java.awt.Color[r=0,g=255,b=0]

So far so good. I now played the hunch and changed the CW text element’s style name from ‘Colors_M_Strings’ to ‘yair’ and luckily the new green color took effect!

So we can now set any style color (and underline it by enclosing the text in a non-target-url hyperlink), as long as we define a style name for it using Prefs.setColorPref. How can we ensure the color uniqueness for multiple colors? The answer was to simply use the integer RGB values of the requested color, something like ‘[47,0,255]‘.

But we still have the hyperlinked (underlined) space before our text - how do we get rid of it? I tried to set the relevant LinkStartTokens entry to -1 but could not: unlike SyntaxTokens which are modifiable Java objects, LinkStartTokens is an immutable numeric vector. I could however set its URL target to null ([]) to prevent the mouse cursor to change when hovering over the space character, but cannot remove the underline. I then had an idea to simply hide the underline by setting the character style to the CW’s background color. The hard part was to come up with this idea - implementation was then relatively easy:

% Get a handle to the Command Window component
mde = com.mathworks.mde.desk.MLDesktop.getInstance;
cw = mde.getClient('Command Window');
xCmdWndView = cw.getComponent(0).getViewport.getComponent(0);

% Store the CW background color as a special color pref
% This way, if the CW bg color changes (via File/Preferences),
% it will also affect existing rendered strs
cwBgColor = xCmdWndView.getBackground;
com.mathworks.services.Prefs.setColorPref('CW_BG_Color',cwBgColor);

% Now update the space character's style to 'CW_BG_Color'
% See within the code: setElementStyle(docElement,'CW_BG_Color',...)

Having thus completed the bulk of the hard detective/inductive work, I now had to contend with several other obstacles before the code could be released to the public:

  • Older Matlab versions (e.g., 7.1 R14) uses the Document style elements slightly differently and I needed to find a solution that will work well on all Matlab 7 versions (this took quite some time…)
  • If the text is not newline (’\n’)-terminated, sometimes it is not rendered properly. Adding a forced CW repaint() invocation helped solve much of this problem, but some quirks still remain (see cprintf’s help section)
  • Multi-line text (’abra \n kadbra’) creates several style elements which needed to be processed separately
  • Debugging the code was very difficult because whenever the debugger stopped at a breakpoint, ‘k>>’ is written to the CW thereby ruining the displayed element! I had to devise non-trivial instrumentation and post-processing (see within the code).
  • Taking care of exception handling, argument processing etc. to ensure foolproof behavior. For example, accepting case-insensitive and partial (unique) style names.

Bottom line: we now have a very simple and intuitive utility that is deceivingly simple, but took a few dozen hours of investigation to develop. I never imagined it would be so difficult when I started, but this just makes the engineering satisfaction greater :-)

Any sufficiently advanced technology is indistinguishable from magic - Arthur C. Clarke

As usual, your comments and feedback are most welcome

Addendum (May 15, 2009): CPRINTF was today chosen as the Matlab Central File Exchange Pick of the Week. That was fast! - thanks Brett :-)

Addendum (May 18, 2009): CPRINTF was today removed from the Pick of the Week list, after internal MathWorks discussions that came to a conclusion that by posting CPRINTF on an official Matlab blog it might appear as an official endorsement of undocumented features. I can certainly understand this, so no hard feelings…

Bookmark and Share

cellfun - undocumented performance boost

May 11th, 2009

Matlab’s built-in cellfun function has traditionally enabled several named (string) processing functions such as ‘isempty’. The relevant code would look like this:

data = cellfun('isempty',cellArray);

In recent years, newer Matlab releases has added support for function handles, so the previous code snippet can now be written as follows:

data = cellfun(@isempty,cellArray);

The newer function-handle format is “cleaner” and more extensive than the former format, accepting any function, not just the limited list of pre-specified processing function names (’isreal’, ‘islogical’, ‘length’, ‘ndims’, ‘prodofsize’). Some have even reported that the older format has limitations vis-a-vis compilation etc.

All this is well known and documented. However, it turns out that, counter-intuitively (and undocumented), the older format is actually much faster than the newer format for those pre-specified processing function names. The reason appears to be that ‘isempty’ (as well as the other predefined string functions) uses specific code-branches optimized for performance:

>> c = mat2cell(1:1e6,1,repmat(1,1,1e6));
>> tic, d=cellfun('isempty',c); toc
Elapsed time is 0.115583 seconds.
>> tic, d=cellfun(@isempty,c); toc
Elapsed time is 7.493989 seconds.

Perhaps a future Matlab release will improve cellfun’s internal code, to check for function-handle equality to the optimized functions, and use the optimized code branch if possible. When I posted this issue today as a correction to a reader’s misconception, Matlab’s Loren Shure commented as follows:

We could improve cellfun to check function handles to see if they match specified strings. Even then MATLAB would have to be careful in case the user has overridden the built-in version of whatever the string points to.

While this comment seems to imply that the performance boost feature will be maintained and possibly improved in future releases, users should note that this is not guarantied. One could even argue that future code optimizations would be applied to the new (function-handle) format rather than the old string format. The performance pendulum might also change based on user platform. Therefore, users for whom performance is critical should always test both versions on their target system: ‘isempty’ vs. @isempty etc. (note that the corresponding function for ‘prodofsize’ is @numel).

Bookmark and Share