Quantcast
Channel: Undocumented Matlab
Viewing all 219 articles
Browse latest View live

Transparent uipanels

$
0
0

A well-known Matlab limitation is that component position vectors must be specified as either ‘normalized’ or some fixed-sized value, but not in combination. For example, we cannot place a button in the center of the screen (normalized x/y=0.5) with a fixed sized width/height. Either all position elements are normalized, or all are fixed. Most Matlab GUIs that I’ve seen keep the normalized units, with the result that buttons look bloated or shrunken when the figure is resized:

hButton = uicontrol('Units','norm', 'Position',[0.5,0.5,0.15,0.15], 'String','click me!');

bad-looking resized normalized button

bad-looking resized normalized button

A common way to address this latter limitation is to use a borderless containing uipanel at the requested normalized position, and place a fixed-sized component as a child of that panel:

bgColor = get(gcf,'Color');
hPanel = uipanel('Units','norm', 'Position',[0.5, 0.5, 0.45, 0.45], 'BorderType','none', 'BackgroundColor',bgColor);
hButton = uicontrol('Parent',hPanel, 'Units','pixels', 'Position',[0,0,60,20], 'String','click me!');

fixed-size button at normalized position

fixed-size button at normalized position

This works well in simple figures, where there is nothing beneath the panel/control. Resizing the figure will keep the button centered, while preserving its 60×20 size. But what happens if we have an axes beneath? In this case we encounter another Matlab limitation, that a top-most control always occludes (hides) an overlapped component. This is due to the fact that Matlab GUI uses heavyweight controls and containers, which do not allow transparency. For this reason, we cannot show a plot chart as the background of a table or listbox, for example. The result is that our panel will occlude the axes for a horrible-looking effect:

t = 1:.01:100;
plot(t, cos(t), 'r');
bgColor = get(gcf,'Color');
hPanel = uipanel('Units','norm', 'Position',[0.5, 0.5, 0.45, 0.45], 'BorderType','none', 'BackgroundColor',bgColor);
hButton = uicontrol('Parent',hPanel, 'Units','pixels', 'Position',[0,0,60,20], 'String','click me!');

panel occluding a plot chart

panel occluding a plot chart

Which is where today’s undocumented feature comes in handy: simply set the uipanel’s BackgroundColor to ‘none’ and the panel will become transparent:

set(hPanel,'BackgroundColor','none')

transparent panel

transparent panel

The reason that uipanel does not obey the occlusion limitation is simply because it is not really a control at all: Most Matlab GUI controls are simple wrappers for the standard Java Swing component (buttons for JButton, listboxes for JListbox etc.). However, uipanel is not a wrapper for JPanel, as we might have expected, but rather implemented as as internal Matlab component that groups HG objects for onscreen display, and possibly paints the border (a uipanel‘s title is a simple text control once again) as a simple rectangle. This is the reason why Matlab’s borders look so different than JPanel‘s. This enabled Matlab to include the back-door of the ‘none’ BackgroundColor, which works for panels but not for any other GUI control.

While the BackgroundColor property is a well-documented property, the ability to specify a colorspec of ‘none’ is not documented.

Note that setting the BackgroundColor to ‘none’ issues the following warning that you can ignore at your own risk:

Warning: "Setting the ColorSpec to 'none' for a uicontainer will not be allowed in a future release."

To ignore such warnings, simply issue the following Matlab command:

warning  off    MATLAB:hg:ColorSpec_None
warning('off', 'MATLAB:hg:ColorSpec_None');  % equivalent alternative

p.s. – using a transparent panel in this manner is not necessary in certain cases (e.g., when the axes is added after the control, not before it as above). However, relying on such side-effects is not advised at all, for obvious reasons.

I look forward to the day when Matlab controls will be able to become truly transparent, and when the position and size units could be specified separately, so that use of such back-door kludges will not be necessary. After all, designing a GUI is supposed to resemble an art, not brain surgery…

 
Related posts:
  1. Transparent Matlab figure window Matlab figure windows can be made fully or partially transparent/translucent or blurred - this article explains how...
  2. Panel-level uicontrols Matlab's uipanel contains a hidden handle to the title label, which can be modified into a checkbox or radio-button control...
  3. Bug and workaround in timeseries plot Matlab's internal hgconvertunits function has a bug that affects timeseries plots. Luckily there is a simple workaround....
  4. Getting default HG property values Matlab has documented how to modify default property values, but not how to get the full list of current defaults. This article explains how to do this. ...
 

Animated busy (spinning) icon

$
0
0

Matlab includes a wide variety of internal widgets (GUI components) that could be very useful in our GUIs. One such widget is an animated spinning icon, which is often used by Matlab itself and numerous toolboxes to illustrate a running task:

Sample usage of an animated spinning icon

Sample usage of an animated spinning icon

One of the internal widgets that are readily-available for use in our Matlab GUI and displays a similar (but not identical) spinning icon is BusyAffordance, which is included in the built-in com.mathworks.widgets package. BusyAffordance creates a visible panel with an animated spinning icon and optional text label as long as the panel’s object is in the “started” mode (the mode can be started/stopped numerous times).

Animated spinner icon

Animated spinner icon

The usage is very simple:

try
    % R2010a and newer
    iconsClassName = 'com.mathworks.widgets.BusyAffordance$AffordanceSize';
    iconsSizeEnums = javaMethod('values',iconsClassName);
    SIZE_32x32 = iconsSizeEnums(2);  % (1) = 16x16,  (2) = 32x32
    jObj = com.mathworks.widgets.BusyAffordance(SIZE_32x32, 'testing...');  % icon, label
catch
    % R2009b and earlier
    redColor   = java.awt.Color(1,0,0);
    blackColor = java.awt.Color(0,0,0);
    jObj = com.mathworks.widgets.BusyAffordance(redColor, blackColor);
end
jObj.setPaintsWhenStopped(true);  % default = false
jObj.useWhiteDots(false);         % default = false (true is good for dark backgrounds)
javacomponent(jObj.getComponent, [10,10,80,80], gcf);
jObj.start;
    % do some long operation...
jObj.stop;

Note how I’ve used the javacomponent function to place the BusyAffordance object onscreen, at position 10,10 of the current Matlab figure, and gave it an initial size of 80×80 pixels.

When the object is stop()ed, the icon and label are removed by default, but can be displayed un-animated (non-spinning) via the PaintsWhenStopped property:

BusyAffordance started... (animated spinning icon)

BusyAffordance started...
(animated spinning icon)

   
...stopped (PaintsWhenStopped = false)

...stopped
(PaintsWhenStopped = false)

   
...stopped (PaintsWhenStopped = true)

...stopped
(PaintsWhenStopped = true)

The small-icon (16×16) variant of the BusyAffordance control is used by another internal Matlab component, ProgressBarDialog. This control presents an animated progress-bar dialog window, similar to Matlab’s built-in waitbar function but with an animated circular busy icon:

d = com.mathworks.mlwidgets.dialog.ProgressBarDialog.createProgressBar('test...', []);
d.setValue(0.75);                        % default = 0
d.setProgressStatusLabel('testing...');  % default = 'Please Wait'
d.setSpinnerVisible(true);               % default = true
d.setCircularProgressBar(false);         % default = false  (true means an indeterminate (looping) progress bar)
d.setCancelButtonVisible(true);          % default = true
d.setVisible(true);                      % default = false

ProgressBarDialog with animated BusyAffordance

ProgressBarDialog with animated BusyAffordance

For those interested, the 16×16 animated GIF used here is spinner.gif, which can be found in %matlabroot%/java/jar/mlwidgets.jar (remember that JAR files are simply ZIP files, so they can be opened in WinZip/WinRar etc.). BusyAffordance also includes a 32×32 icon which is not available as a separate icon file. From this we learn that BusyAffordance probably creates this variant (and possibly also the 16×16 one) on-the-fly (programmatically).

For additional information on BusyAffordance, com.mathworks.widgets and other internal Matlab components, refer to chapter 5 in my Matlab-Java programming book.

As with other internal Matlab components, I categorized this feature as “High risk of breaking in a future release“. Still, BusyAffordance has existed in its present form since R2010a (and with a slightly different interface for years before then), so there’s a good chance that it will continue as-is in the foreseeable future. Then again, it might be removed as early as the next upcoming release, without prior warning…

More advanced animated busy indications, including automated percentage and time-remaining labels, can be specified using JBusyComponent, which is a JXLayer decorator that can be applied to any displayable component. In R2013b or newer that use Java7, we can also use the built-in JLayer class. We can also simply embed the animated GIF image directly in our GUI, as I explained here.

In the past I have already shown how to use other internal components in Matlab’s com.mathworks.widgets package, including a syntax-highlighted labels and text panes that can be embedded in our GUI.

Have you used BusyAffordance or some other internal Matlab component in a neat way in your GUI? if so, please do tell us about it in a comment below.

 
Related posts:
  1. Displaying animated GIFs It is possible to easily display animated images in Matlab figure windows. ...
  2. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
  3. Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
  4. FindJObj GUI – display container hierarchy The FindJObj utility can be used to present a GUI that displays a Matlab container's internal Java components, properties and callbacks....
 

Matlab callbacks for Java events in R2014a

$
0
0

Exactly five years ago, in one of this blog’s first articles, I wrote an article explaining how to trap the standard Java Swing events in Matlab, in order to achieve much more extensive behavior customizability than Matlab’s standard uicontrols. Three years ago I wrote a related article showing how to trap any Java events as simple Matlab callbacks, even those from custom Java classes. This worked very well over the years, until now.

Over the past few weeks, several people have commented and emailed me about a problem that occurs in R2014a but not in earlier releases: Whereas Java objects in R2013b and earlier automatically exposed their public events as Matlab callbacks, they no longer do so in R2014a.

As a simple example to illustrate the point, let’s take a simple Java JButton and modify its label when the mouse moves over it, using the mouseEntered, mouseExited events. In R2013b and earlier this was pretty easy:

% Create and display a simple JButton
jButton = javax.swing.JButton('click me');
javacomponent(jButton, [50,50,80,20], gcf);
 
% Set the Matlab callbacks to the JButton's events
set(jButton, 'MouseEnteredCallback', @(h,e)set(jButton,'Text','NOW !!!'))
set(jButton, 'MouseExitedCallback',  @(h,e)jButton.setText('click me'))

Dynamic Matlab callback behavior based on Java events

(Note how I used two distinct variants to set the button’s text, using either the Matlabized Text property with the set function, or the standard JButton’s setText() method. We can use either of these variants: they are equivalent and largely a matter of personal taste, although the Java method is generally preferable.)

Unfortunately, in R2014a we get an error, since the jButton object no longer exposes its events as Matlab callbacks:

>> set(jButton, 'MouseEnteredCallback', @(h,e)set(jButton,'Text','NOW !!!'))
The name 'MouseEnteredCallback' is not an accessible property for an instance of class 'javax.swing.JButton'.

The solution – wrap the Java reference in a Matlab handle

Do not set Matlab callbacks on the so-called “naked” Java reference. Instead, wrap the reference with a Matlab handle:

>> jButton = handle(jButton, 'CallbackProperties');
hjButton =
	javahandle_withcallbacks.javax.swing.JButton
 
% we can now set the callbacks on jButton as before

The simple act of using the handle wrapper rather than the naked Java reference also prevents some memory leaks, as I explained here. While you’re at it, also wrap (or more precisely, auto-delegate) the Java reference with a javaObjectEDT, if it is a Swing GUI component, in order to avoid EDT timing issues. Using these wrappers form two of my six rules for safe Java programming in Matlab, that I outlined in section 1.5 of my Matlab-Java programming book. Anyone who followed that advice would not need to modify their code for R2014a. Even if you didn’t, the solution is quite painless: simply add the wrapper line for any Java reference whose events you wish to trap.

Note that the explanation above relates to all Java objects that expose events, not just for GUI ones. I used JButton merely to illustrate the point.

 
Related posts:
  1. Matlab callbacks for Java events Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
  2. FindJObj – find a Matlab component’s underlying Java object The FindJObj utility can be used to access and display the internal components of Matlab controls and containers. This article explains its uses and inner mechanism....
  3. JMI – Java-to-Matlab Interface JMI enables calling Matlab functions from within Java. This article explains JMI's core functionality....
  4. Matlab-Java interface using a static control The switchyard function design pattern can be very useful when setting Matlab callbacks to Java GUI controls. This article explains why and how....
 

Plotly graphs in IPython Notebook

$
0
0

Last December, I hosted an article on plot.ly‘s awesome online plotting interface for Matlab. Today, I wish to welcome Andrey Dimitrov, a plot.ly engineer, who will discuss generating Plotly graphs in IPython Notebooks, all from within Matlab. The Plotly idea, of generating online interactive graphs, is radically different from Matlab’s standard static plots and deserves a second look. Note that Plotly is a commercial venture.

Overview

The Plotly Matlab API enables leveraging the power of Plotly graphs conveniently from your Matlab environment, meaning that you can make a graph like this in Matlab:

You can work in Matlab, share your graphs and data, and then edit it together online. It’s all backed up, collaborative, and can be edited with other APIs and the GUI. It’s free, embeddable, and keeps data and graphs together.

The API provides a set of functions that structure your data and send it to Plotly. All editing can be done through the API or the online GUI. In addition, the Plotly wrapper function can take away all the hassle of learning a new graphing syntax. Just build your figures in Matlab as usual and send them to Plotly with one call to the wrapper.

This notebook goes through some usage scenarios to get Matlab users started with the tool. A version of this post (with several more examples) was also written as an IPython Notebook. Some steps are specific to making everything work in an IPython notebook, but you can always skip through those and get to the good stuff.

A simple example

First, we need to start a Matlab server. In the IPython Notebook:

In [1]:
import pymatbridge as pymat
ip = get_ipython()
pymat.load_ipython_extension(ip, matlab='C:\Users\Andrey\matlab_shortcut.lnk')

This starts Matlab on the local computer and we can now enter Matlab commands in our IPython Notebook:

Starting Matlab on http://localhost:60199
 visit http://localhost:60199/exit.m to shut down same
...Matlab started and connected!

Note to Windows users: Python doesn’t like file paths with spaces! Above, a shortcut to matlab.exe was created and placed it in a path that did not contain spaces. It’s a bit of a hack, there are better ways to do it I’m sure.

Now we are ready to run Matlab. Let’s set up the Plotly environment next. This needs to be done only once per session. The next few lines import the Plotly Matlab API and sign in to your account. For these examples we are using the Matlab-demos account. You can sign up at Plotly to get a username and key (more info), or just use the Matlab-demos username and key below to make these examples work. In Matlab:

In [2]:
%%matlab
api_path = 'C:\Users\Andrey\Dropbox\ANDREY\PLOTLY\Matlab-api\plotly';
addpath(genpath(api_path))
signin('Matlab-demos', '3qhoowzv5n');  % account username & key

We are now signed in and can convert and publish the Matlab figures in Plotly. The Plotly Matlab API helps generate data and layout data structures that contain all the information needed to make a plot. The plotly command sends these to the server and the result is displayed via the response variable. In it, a URL points to the generated plot online. In this notebook, we focus of the Plotly wrapper. The fig2plotly command at the end of the code will convert the current figure into a format that Plotly understands and publish it.

Let’s make a simple plot in Matlab and publish it to Plotly:

In [3]:
% some random points
my_random_data = rand(20,4);
 
% a 2D scatter plot with size and color inputs
figure
scatter(my_random_data(:,1), my_random_data(:,2), 100*my_random_data(:,3), my_random_data(:,4), 'filled')
 
% Convert the static figure into an online Plotly chart
response = fig2plotly();
 
High five! You successfully sent some data to your account on Plotly. View your plot in your browser at https://plot.ly/~Matlab-demos/0 or inside your plot.ly account where it is named 'untitled'.

The plot has been sent to the Matlab-demos account and the command returns the unique URL https://plot.ly/~Matlab-demos/0 where anyone can view the rendered graph. By default, the plot is named “untitled”. In the following examples, we see how the command allows the user to give a custom name, otherwise it will try to extract it from the figure title.

Every plotly graph URL can be embedded in HTML as wrapped in an IFrame. In fact, the Plotly figure above can be embedded in an HTML (as in this webpage) using the following HTML code:

<iframe src="https://plot.ly/~Matlab-demos/0/400/320/" width="400" height="320" seamless="seamless" scrolling="no"></iframe>

Here’s a quick Python utility function that will embed a plotly graph in IPython Notebooks:

In [4]:
from IPython.display import HTML
 
def show_plot(url, width=700, height=500):
    s = '<iframe height="%s" id="igraph" scrolling="no" seamless="seamless" src="%s" width="%s"></iframe>' %\
    (height+50, "/".join(map(str,[url, width, height])), width+50)
    return HTML(s)

To see the resulting plot, we only need to input the following command:

In [5]:
show_plot('https://plot.ly/~Matlab-demos/0')

(resulting in a display of the interactive chart above)

Example 2: Convex Hull

Note: The original example data can be found at the Matlab Plot Gallery.

In [6]:
%%matlab
% This is an example of how to add text to a plot in Matlab.
% Read about the <http://www.mathworks.com/help/matlab/ref/text.html |text|> function in the Matlab documentation.
% Go to <http://www.mathworks.com/discovery/gallery.html Matlab Plot Gallery>
 
% Load the points for creating a spline curve
load('C:\Users\Andrey\Dropbox\ANDREY\PLOTLY\Matlab_Examples\Add_Text_to_Plot_1\splineData');
 
% Plot the points for the spline curve
figure;
plot(points(:,1), points(:,2), ':ok');
hold on;
 
% Plot the spline curve
plot(x, y, 'LineWidth', 2);
axis([0.5 7 -0.8 1.8]);
 
% Add a title and axis labels
title('The Convex-Hull Property');
xlabel('x');
ylabel('y');
 
% Label points 3, 4, & 5 of the spline curve
xt = points(3,1) - 0.05;
yt = points(3,2) - 0.10;
text(xt, yt, 'Point 3', 'FontSize',12);
 
xt = points(4,1) - 0.05;
yt = points(4,2) + 0.10;
text(xt, yt, 'Point 4', 'FontSize',12);
 
xt = points(5,1) + 0.15;
yt = points(5,2) - 0.05;
text(6.1,.5, 'Point 5', 'FontSize',12);
 
% Convert the static figure into an online Plotly chart
response = fig2plotly();

This time, the plot was named “The Convex Hull Property”. Back in the IPython Notebook:

In [7]:
show_plot('https://plot.ly/~Matlab-demos/1')
 
Out [7]:

Sweet! Let’s keep going…

We will reuse the same code and add some more inputs to the fig2plotly command. We can specify explicitly the figure object that will be published (it doesn’t need to be the current one). In addition, we add ‘open’ to turn off the automatic opening of a browser window with the response URL, and we ‘strip’ the plot of all Matlab styling and revert to Plotly defaults. This allows users to use Plotly’s styling capabilities from the API of at the online UI.

The Matlab code is as above, except for the last (fig2plotly) line:

% Convert the static figure into an online Plotly chart
hFig = gcf;  % any figure, for now we use the current
response = fig2plotly(hFig, 'strip',true, 'open',false, 'name','Stripped plot');
In [8]:
show_plot('https://plot.ly/~Matlab-demos/2')
 
Out [8]:

Example 3: Multiple Plots

In [9]:
%%matlab
% Create data
t = linspace(0,2*pi);
t(1) = eps;
y = sin(t);
 
% Place axes at (0.1,0.1) with width and height of 0.8
figure;
handaxes1 = axes('position', [0.1 0.1 0.8 0.8]);
 
% Main plot
plot(t, y);
xlabel('t');
ylabel('sin(t)');
set(handaxes1, 'box', 'off');
 
% Adjust X/Y label font
set(get(gca, 'xlabel'), 'fontsize',16, 'fontweight','bold');
set(get(gca, 'ylabel'), 'fontsize',16, 'fontweight','bold');
 
% Place second set of axes on same plot
handaxes2 = axes('position', [0.6 0.6 0.2 0.2]);
fill(t, y.^2, 'g');
set(handaxes2, 'box', 'off');
xlabel('t');
ylabel('(sin(t))^2');
 
% Adjust X/Y label font
set(get(handaxes2,'xlabel'), 'fontname','times')
set(get(handaxes2,'ylabel'), 'fontname','times')
 
% Add another set of axes
handaxes3 = axes('position', [0.25 0.25 0.2 0.2]);
plot(t, y.^3);
set(handaxes3, 'box','off');
xlabel('t');
ylabel('(sin(t))^3');
 
% Convert the static figure into an online Plotly chart
response = fig2plotly(gcf, 'name','Multiple_Plots');
In [10]:
show_plot('https://plot.ly/~Matlab-demos/3')
 
Out [10]:

Check out more examples interactive Plotly and Matlab graphs in IPython notebooks here.

 
Related posts:
  1. Plotly graphs Plotly charts can be created and customized in Matlab. ...
  2. JFreeChart graphs and gauges JFreeChart is an open-source charting library that can easily be integrated in Matlab...
  3. Pinning annotations to graphs Annotation object can be programmatically set at, and pinned-to, plot axes data points. ...
  4. GUI automation using a Robot This article explains how Java's Robot class can be used to programmatically control mouse and keyboard actions...
 

Bar plot customizations

$
0
0

Bar charts are a great way to visualize data. Matlab includes the bar function that enables displaying 2D bars in several different manners, stacked or grouped (there’s also bar3 for 3D bar-charts, and barh, bar3h for the corresponding horizontal bar charts).

Displaying stacked 1D data

bar is basically a high-level m-file wrapper for the low-level specgraph.barseries object. Such wrappers are generally a good thing, assigning default property values, checking the input data for illegal values etc. But in some cases, they are simply too smart. One such case happened to me a few days ago, when I needed to display a stacked chart of some data values. This works great when the data is a 2D matrix, but when the data happens to be 1D (a single row), bar decides to display the values in separate bars (left screenshot), rather than in a single stacked bar (right screenshot), even when I specifically ask for a ‘stacked’ graph:

bar([6,4,1], 'Stacked');

Default bar plot of 1D data

Default bar plot of 1D data

  
Bar plot of 1D data - stacked

Bar plot of 1D data - stacked


I could of course revert to the lower-level specgraph.barseries. But in this case the simple workaround was to add a dummy data row of Nan values, tricking bar into thinking it’s a 2D data. Since Nan values are never plotted in Matlab, we get the requested stacked bar, alongside an empty bar next to it. All we need to do now is to delete the extra tick-label for the dummy (empty) bar and we’re done:

bar([6,4,1; nan(1,3)], 'Stacked');
set(gca,'xtick',1)

or, more generally (taking care of both 2D and 1D data):

bar([data; nan(size(data))],'Stacked');
set(gca, 'xtick',1:size(data,1));

Displaying data labels

One of the features that I miss most in Matlab bar-charts is the ability to easily add data labels next to the colored patches. This can be added programmatically as I’ll just show, but it would be much better if there were properties that controlled this. Here’s my implementation:

First, let’s display a simple stacked bar chart:

data = [6,4,1; 5,2,2; 4,0,0; 2,0,1; 0,2,0; 0,1,1];
hDataSeries = bar(data,'stacked');
set(gca, 'xlim',[0,7], 'box','off');

Default bar plot of 2D data

Default bar plot of 2D data

Now let’s add the bar totals on top of the bars:

sumTotals = sum(data,2);
sumTotals = sumTotals(~isnan(sumTotals));
labels = arrayfun(@num2str,sumTotals,'uniform',false);
hText = text(1:size(data,1), sumTotals, labels);
set(hText, 'VerticalAlignment','bottom', 'FontSize',8, 'Color','b');

Bar plot with totals

Bar plot with totals

Now let’s add the individual data-series labels, but only next to bars that have 2 or more components:

hPatches = get(hDataSeries,'Children');
try hPatches = cell2mat(hPatches); catch, end  % no need in case of single patch
xData = get(hPatches(1),'XData');
xPos = xData(end,:) + 0.01;
yData = get(hPatches,'YData');
try yData = cell2mat(yData); catch, end
barYs = yData(2:4:end,:);
barValues = diff([zeros(1,size(barYs,2)); barYs]);
barValues(bsxfun(@minus,barValues,sum(barValues))==0) = 0;  % no sub-total for bars having only a single sub-total
yPos = yData(1:4:end,:) + barValues/2;
xPos = xPos(ones(1,size(yPos,1)),:);
xPos(barValues==0)      = [];  % remove entries for empty bars patches
yPos(barValues==0)      = [];  % remove entries for empty bars patches
barValues(barValues==0) = [];  % remove entries for empty bars patches
labels = strcat(' ', arrayfun(@num2str,barValues(:),'uniform',false));
hText = text(xPos(:), yPos(:), labels);
set(hText, 'FontSize',8);

Finally, add the legend and we’re done:

hLegend = legend(hDataSeries, {'Blue','Green','Red'});
set(hLegend, 'FontSize',8);

Bar plot with totals & legend

Bar plot with sub-totals & legend

Additional customization of the bar patches can be made using the patch handles, which are included as children of the returned hDataSeries handles:

hDataSeries = bar(...);
hPatches = get(hDataSeries, 'Children');
try hPatches = cell2mat(hPatches); catch, end  % no need in case of single patch

Note: hDataSeries is an array of handles, one per data column. Each handle is an hggroup of patches. As with all patches, we can customize their face and edge line-style, width, color, transparency, shading/lighting etc.

 
Related posts:
  1. Undocumented scatter plot behavior The scatter plot function has an undocumented behavior when plotting more than 100 points: it returns a single unified patch object handle, rather than a patch handle for each specific...
  2. Undocumented scatter plot jitter Matlab's scatter plot can automatically jitter data to enable better visualization of distribution density. ...
  3. Bug and workaround in timeseries plot Matlab's internal hgconvertunits function has a bug that affects timeseries plots. Luckily there is a simple workaround....
  4. Plot LimInclude properties The plot objects' XLimInclude, YLimInclude, ZLimInclude, ALimInclude and CLimInclude properties are an important feature, that has both functional and performance implications....
 

checkClass

$
0
0

Over the past few years I have shown numerous uses of Java components in Matlab, many of them built-into the Matlab environment and can be used as-is. I have been asked many times how I uncover these components and how I discover how to use them. The short answer is that this is indeed often not easy. The blog articles (and my book) only present “success stories“, i.e. cases where I was able to uncover the behavior, functionality and usage of such components; they do not present the numerous other cases where I have not been so successful.

Still, over the course of the past 10-15 years, I developed several tools that help me become more efficient in this work, and I’ve posted most of these on the File Exchange. I’ve already written here about the FindJObj utility, both as a means for uncovering the underlying Java reference of Matlab GUI controls, and as a means to visualize the GUI hierarchy of a specified window or container. I also wrote about my uiinspect utility, which analyzes the specified object in a compact and intuitive GUI window.

Today I wish to complete the picture by describing my checkClass utility. checkClass is more limited than uiinspect in the types of objects that it can analyze (almost only Java objects) and the information that it presents (for example, callbacks and properties are not listed separately). checkClass‘s main benefit is the fact that it is a very lightweight (230 lines of code), fast, GUI-less console application. checkClass highlights the differences between the analyzed class and its superclass, which is especially useful when investigating the functionality of objects. During the course of my work, I use checkClass for 95% of my investigations, and uiinspect/findjobj only for the remainder. For Java objects at least, a detailed console listing of the methods is quite enough, since properties are typically accessed via getPropName()/setPropName() accessor methods. The combination of checkClass and uiinspect can be very useful when investigating a new Java library or integrating a 3rd-party API.

Here is a sample output for the com.mathworks.mwswing.MJToggleButton class:

>> jButton = com.mathworks.mwswing.MJToggleButton;
>> checkClass(jButton)  % or: jButton.checkClass
Class com.mathworks.mwswing.MJToggleButton (uiinspect)

Superclass: javax.swing.JToggleButton

Methods in MJToggleButton missing in JToggleButton:
   hasFlyOverAppearance() : boolean
   hideText()
   isAutoMnemonicEnabled() : boolean
   isTextHidden() : boolean
   setAutoMnemonicEnabled(boolean)
   setFlyOverAppearance(boolean)
   setFocusTraversable(boolean)
   unHideText()

Methods inherited & modified by MJToggleButton:
   getForeground() : java.awt.Color
   getParent() : java.awt.Container
   isFocusTraversable() : boolean
   paint(java.awt.Graphics)
   setAction(javax.swing.Action)
   setModel(javax.swing.ButtonModel)
   setText(java.lang.String)

Interfaces in JToggleButton missing in MJToggleButton:
   javax.accessibility.Accessible

Interfaces in MJToggleButton missing in JToggleButton:
   com.mathworks.mwswing.ExtendedButton

The interpretation is quite intuitive. For example, isTextHidden() is a class method that accepts no input args and returns a boolean result; setText() is a method that accepts a string and returns no result.

Each of the hyperlinks is linked to another checkClass on the specified class. This makes investigation of classes and their interconnections quite easy.

From this output, we learn that the MathWorks MJToggleButton class added the FlyOverAppearance and AutoMnemonicEnabled properties, together with their associated accessor methods. We also learn that MJToggleButton added a non-property method: hideText().

Finally, setFocusTraversable() was added as a setter method to the FocusTraversable property: the getter method isFocusTraversable() is already defined in the ancestor JToggleButton class (which is part of the standard Swing package) – MJToggleButton simply added a setter method.

Some classes (e.g., MJSlider) appear to be plain wrappers for their Swing ancestor:

>> checkClass('com.mathworks.mwswing.MJSlider')
Class com.mathworks.mwswing.MJSlider (uiinspect)

Superclass: javax.swing.JSlider

Methods inherited & modified by MJSlider:
    setModel(javax.swing.BoundedRangeModel)

Interfaces in JSlider missing in MJSlider:
    javax.accessibility.Accessible
    javax.swing.SwingConstants

In other cases, MathWorks has extensively modified the base class functionality:

>> checkClass com.mathworks.mwswing.MJToolBar
Class com.mathworks.mwswing.MJToolBar (uiinspect)

Superclass: javax.swing.JToolBar

Methods in MJToolBar missing in JToolBar:
   addGap()
   addGap(int)
   addToggle(javax.swing.Action) : javax.swing.JToggleButton
   configure(com.mathworks.mwswing.ExtendedButton) (static)
   configureButton(com.mathworks.mwswing.MJButton) (static)
   configureButton(com.mathworks.mwswing.MJToggleButton) (static)
   configureButton(com.mathworks.mwswing.MJToggleButton, boolean) (static)
   createMacPressedIcon(javax.swing.Icon) : javax.swing.Icon (static)
   dispose()
   dispose(javax.swing.JToolBar) (static)
   getComponentExcludingMoreButton(int) : java.awt.Component
   getFlyOverBorder() : javax.swing.border.Border (static)
   getToggleFlyOverBorder() : javax.swing.border.Border (static)
   isFloating() : boolean
   isMarkedNonEssential(javax.swing.JComponent) : boolean (static)
   isMorePopupEnabled() : boolean
   isOnMoreMenu(java.awt.Component) : boolean
   markAsNonEssential(javax.swing.JComponent) (static)
   setArmed(boolean)
   setInsideToolbarBorder()
   setMorePopupEnabled(boolean)

Methods inherited & modified by MJToolBar:
   add(javax.swing.Action) : javax.swing.JButton
   addSeparator()
   addSeparator(java.awt.Dimension)
   doLayout()
   getMinimumSize() : java.awt.Dimension
   getPreferredSize() : java.awt.Dimension
   removeAll()

Interfaces in JToolBar missing in MJToolBar:
   javax.accessibility.Accessible
   javax.swing.SwingConstants

Static fields in MJToolBar missing in JToolBar:
   MORE_BUTTON_NAME                  = 'MoreButton'
   MORE_MENU_INELIGIBLE_PROPERTY_KEY = 'MoreMenuIneligible'
   NON_ESSENTIAL_PROPERTY_KEY        = 'NonEssentialComponent'

Sub-classes in MJToolBar missing in JToolBar:
   com.mathworks.mwswing.MJToolBar$VisibleSeparator

In this example, we see that the MJToolBar class includes 3 variants for the configureButton() method, and 2 variants for the dispose() method, accepting a different number and/or type of input parameters.

Similarly, for the CheckBoxList class:

>> checkClass com.mathworks.mwswing.checkboxlist.CheckBoxList
Class com.mathworks.mwswing.checkboxlist.CheckBoxList (uiinspect)

Superclass: com.mathworks.mwswing.MJList
Superclass: javax.swing.JList

Methods in JList missing in CheckBoxList:
   JList(java.lang.Object[])
   JList(java.util.Vector)

Methods in CheckBoxList missing in JList:
   CheckBoxList(java.util.List)
   checkAll()
   checkIndex(int)
   checkValue(java.lang.Object)
   constrainViewerToCellHeight() : boolean
   getCellPainter(java.lang.Integer) : java.awt.Component
   getCellPainter(java.lang.Object) : java.awt.Component
   getCellViewerOffset(java.lang.Integer) : java.awt.Dimension
   getCellViewerOffset(java.lang.Object) : java.awt.Dimension
   ...

Here we see that two superclass constructor variants (accepting an array of Objects or a single Vector object) have been replaced by a single constructor that accepts a List object (this is considered a bad programming practice, by the way).

In this case, CheckBoxList extends MJList which is also a Matlab class, which itself extends the standard Swing JList. By default, checkClass compares the specified class object versus the nearest ancestor class that is non-MathWorks. We can modify this behavior by specifying a different super-class level:

>> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 1)  % compare CheckBoxList to com.mathworks.mwswing.MJList
>> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 2)  % compare CheckBoxList to javax.swing.JList (=default behavior)
>> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 3)  % compare CheckBoxList to javax.swing.JComponent (=JList's superclass)
>> checkClass('com.mathworks.mwswing.checkboxlist.CheckBoxList', 4)  % compare CheckBoxList to java.awt.Container (=JComponent's superclass)
% ...and so on (up to java.lang.Object, which is the base class for all Java objects)

checkClass can inspect both class name and class objects. For example:

checkClass('java.lang.String')   % class name
checkClass(javax.swing.JButton)  % class object
 
jButton = javax.swing.JButton('Click me!'); 
jButton.checkClass;  % class object
 
checkClass('com.mathworks.mwswing.MJToolBar')  % class-name
checkClass(com.mathworks.mwswing.MJToolBar)    % class object
 
checkClass(com.mathworks.mde.desk.MLDesktop.getInstance)

Class methods can also be inspected using methodsview or preferably uiinspect; properties and callbacks can be inspected by using get, inspect, or again uiinspect. Users may also try to search the Matlab-supplied m-files for sample usage of these classes. For example, Matlab 7.2’s uisetfont.m uses com.mathworks.mwswing.MJButton. Note that different Matlab releases use internal classes differently. Therefore, searching the m-file code base of different Matlab releases may yield additional clues.

I encourage you to download the checkClass utility and explore its code, and I welcome your feedback.

p.s. – Anyone watching the TV series “The Americans” may have noticed that in the season finale (“Echo“), which aired on May 21, the code listing of the Echo program, is actually that of a GUIDE-created Matlab m-file (linear_array_gui), plus some non-Matlab code (Ada?). Matlab’s GUIDE wasn’t available in the mid-1980s, when the story purportedly takes place, back in the days of a 640KB IBM PC with a single floppy drive, but it’s a nice anachronism. In any case the combination of the Matlab and Ada code would never have run… :-)

 
Related posts:
  1. Tri-state checkbox Matlab checkboxes can easily be made to support tri-state functionality....
  2. Customizing uitree nodes – part 2 This article shows how Matlab GUI tree nodes can be customized with checkboxes and similar controls...
  3. Setting status-bar components Matlab status-bars are Java containers in which we can add GUI controls such as progress-bars, not just simple text labels...
  4. The javacomponent function Matlab's built-in javacomponent function can be used to display Java components in Matlab application - this article details its usages and limitations...
 

Function call timeline profiling

$
0
0

Back in 2012, I wrote an article about the Matlab profiler’s undocumented functionality of storing detailed information about the function-call history, including timing information. I intended to follow up on this with a utility that would bring the data to life, but I never found the time for this. With my upcoming book on Matlab performance now nearing publication (ETA: November 2014), I decided it’s finally time to finish the task. The result is my profile_history utility, available for download on the Matlab File Exchange (open-source):

Usage of profile_history is very easy, based on the latest profiling session:

profile on; surf(peaks); profile_history

Function call timeline profiling (click for full-size image)
Function call timeline profiling (click for full-size image)


The function-call is displayed in a waterfall graph, where thick red lines mark the self (CPU-execution) time, and blue lines mark the calling (parent) functions. Dotted red lines connect the parent (calling) and child (called) functions, such that it is easy to see which function was called, when, and by whom. The graph is interactive: panning and zooming are possible, and clicking on any of the function labels or graph lines opens up the detailed (standard, builtin) profiler report for that function. In addition, an info-box is displayed whenever we move the mouse over the contents. This info-box displays information about the pointed-to call invocation, including its function name, start-time, self-time, time spent in children, total duration and the end time. If the function was called multiple times during the profiling session, then additional information about these other invocations is also displayed. The info-box, dotted waterfall lines, and the red execution lines can be turned on/off, using checkboxes at the bottom of the figure window.

We can also run profile_history on pre-stored profiling data:

profile on; myProgram(); profData=profile('info'); profile_history(profData)

Why is this important?

So yes, this is a cool utility, but does it really add information that was not already available if we dug down in the standard profiler report?

The answer is a definite YES. Let’s take the following simple example:

function perfTest
    for idx = 1 : 10
        pause(0.02);
        nestedFunction();
        subFunction(idx);
    end
 
    function nestedFunction
        pause(0.03);
    end
end
 
function subFunction(idx)
    if idx > 1
        pause(0.05);
    else
        pause(0.5);
    end
end

The standard profiler report simply tells us that perfTest ran once, taking 1.69 secs, calling perfTest>subFunction 10 times running a total of 1.06 secs. There is no information, even in the detailed report, about which of the 10 invocations of subFunction was responsible for the majority of the run-time, or whether all 10 invocations took approximately ~0.1 secs each. Looking at the code above we can see that the first invocation was indeed significantly slower, but in general we do not know that a certain invocation is in fact much slower than the rest.

Enter profile_history: a single look at the output, possibly with a few mouse hovers over the relevant red invocation segments, immediately shows us that the first invocation of subFunction was responsible for the majority of the run-time. If we just improve this single invocation, rather than improve the general case, we achieve the maximal benefit from our performance-tuning effort.

Function call timeline profiling: focus on the first invocation (click for full-size image)

Function call timeline profiling: focus on the first invocation (click for full-size image)

For a detailed discussion of the profiling timing data that underlies profile_history, please refer to my aforementioned article.

Some ideas for potential future development:

  1. event markers (figure open/close, uicontrol actions, I/O, …)
  2. function labels color based on type (GUI/algo/internal/…)
  3. top-down vs. bottom-up presentation
  4. aggregated by function or not (i.e., full waterfall; duplicate function names on different rows)
  5. automatically highlight performance hotspots
  6. integrate in existing Profiler report (profview)
  7. additional info-box data

Let me know what you think of all this in a comment below!

 
Related posts:
  1. Profiling Matlab memory usage mtic and mtoc were a couple of undocumented features that enabled users of past Matlab releases to easily profile memory usage. ...
  2. Function definition meta-info There are multiple ways to retrieve meta-info about functions in Matlab. ...
  3. ismembc – undocumented helper function Matlab has several undocumented internal helper functions that can be useful on their own in some cases. This post presents the ismembc function....
  4. sprintfc – undocumented helper function The built-in sprintfc function can be used to quickly generate a cell-array of formatted strings. ...
 

Java class access pitfalls

$
0
0

A few days ago I consulted to a company that wanted to integrate some of their Java code in Matlab. The Java code compiled ok and ran just fine in the Java environment, but when we wanted to use the relevant Java classes in Matlab we got all sorts of errors. Since I believe that this could be a common problem, and I’m not sure that there’s any other place that does this, I thought to list the possible error causes in today’s article:

  1. Forgetting or mistyping the package name:
    >> jObject = JButton('Click me!');  % missing package name
    Undefined function 'JButton' for input arguments of type 'char'.
    
    >> jObject = java.swing.JButton('Click me!');  % should be javax.swing...
    Undefined variable "java" or class "java.swing.JButton". 
    
    >> jObject = javax.Swing.JButton('Click me!');  % should be javax.swing...
    Undefined variable "java" or class "javax.Swing.JButton". 
    
    >> import java.swing.*  % should be javax.swing... - no error here, only in the next line
    >> jObject = JButton('Click me!');   % missing package name
    Undefined function 'JButton' for input arguments of type 'char'.
    
    >> import java.swing.JButton  % should be javax.swing...
    Error using import
    Import argument 'java.swing.JButton' cannot be found or cannot be imported.
    

    Note: package names are typically lowercase, but 3rd-party packages might not follow this convention! Since Java is case-sensitive, the package name must be exact.

  2. Mistyping the class name. As with package names, Java class names are also case-sensitive. Beware of cases of O/0 (capital-”o” vs. the digit zero), and I/l/1 (capital-”i” vs. lowercase “L” vs. the digit 1). Also note whether the class name includes the underscore (“_”) character.
     
  3. Using a Java class that was compiled using a newer JDK major-version than the JVM used in Matlab. The specific JVM used by Matlab varies across platforms and Matlab releases. On R2014a Win64, the default (pre-installed) version is 1.7, which means that classes compiled using (or targeting) JDK 7 or below are ok, but classes compiled using JDK 8 or above would simply not run:
    >> a = MyJavaClass;
    Undefined function or variable 'MyJavaClass'.
    
    >> a = my.java.Class;
    Undefined variable "my" or class "my.java.Class".
    

    To get Matlab’s current JVM version, use the version command:

    >> version -java
    ans =
    Java 1.7.0_11-b21 with Oracle Corporation Java HotSpot(TM) 64-Bit Server VM mixed mode
    

    The default JVM used in Matlab R14 (7.0) to R2013a (8.1) was 1.6 (=JDK 6); R2013b (8.2) and later use 1.7 (=JDK 7). If you wish to ensure compatibility with earlier Matlab releases, I suggest compiling using JDK 6 rather than 7 or 8. This can easily be modified in all Java IDEs, in the project’s preferences. Remember to reference the corresponding JRE 1.6 libraries as well, rather than the newer JRE ones. In many cases, the Java code would still compile and run properly, even when compiled using the earlier JDK/JRE.

    If downgrading the compilation JDK is not possible (for example, if you do not have access to the source code, or if it uses some new JDK features), then consider installing a newer compatible JVM in Matlab.

    Note that when we try running the Java classes using the java executable (outside Matlab), we do get a meaningful message about the fact that the classes were compiled for a higher JVM version. Unfortunately, this information is simply not being provided by Matlab – just the standard plain error about the function or file not being found. I hope this will be fixed in some future Matlab release.

  4. Forgetting to update the Java classpath. Java has a different classpath than Matlab’s. Class or JAR files placed on Matlab’s path are not recognized. Instead, these files need to be added to the Java classpath, either dynamically within the Matlab session (using the javaaddpath function), or statically (by adding entries to the classpath.txt or javaclasspath.txt files). Read here for additional details. Note that the javaclasspath.txt alternative only exists since R2012b (8.0). You can view the current Java classpath in Matlab using the javaclasspath command.
     
    When updating the Java classpath, either dynamically or statically, beware of the following pitfalls:
    • If you add a folder name to the javaclasspath, then all *.class files are automatically recognized and they will be loaded when first used. However, this does NOT include *.jar or *.zip files placed in these folders. The Java specification requires such files to be added individually to the classpath, using their full pathname.
    • While we can use relative paths when adding elements dynamically (using javaaddpath), we must specify the full pathname when updating the static classpath files.

     

  5. Dependency #1: A class that depends on any other class that is not on the current Java classpath (either dynamic or static). This is typically due to the fact that the class was compiled in a Java IDE where there were multiple referenced libraries, which were not copied to the Matlab classpath. It is not enough to simply place the generated output *.class or *.jar files in Matlab’s Java classpath – the referenced libs must also be placed there. If they are not, then Matlab simply issues the generic error that the function or class cannot be found. Matlab provides no information that this is a dependency error and we must infer this ourselves. Note that it does not matter that the non-existent class might referenced in an obscure portion of the class code that is never reached – the mere fact that there is a reference in the class that cannot be located causes the entire class to fail to load. Debugging this can indeed be nerve wrecking (and another example)… I hope that this too will be fixed in some future Matlab release.
     
  6. Dependency #2: A class on the static Java classpath that depends on another class which is on the dynamic Java classpath. All static classes must depend only on other static classes, since the static classpath is processed before the dynamic one, when the JVM is launched at Matlab startup.
     
  7. Non-public class – Matlab can only access public classes. If the class is private, protected or has package visibility (by not specifying any visibility modifier at all), then the class would not be loadable by Matlab, only by other Java classes. So remember to add the public keyword in the definition of all the Java classes that you wish to directly use in Matlab.
     
  8. Non-public constructor – Matlab can only create objects for non-static classes that have public constructors. If all the class constructors are non-public, then Matlab cannot create a class instance object. In such a case we would get a misleading error message, that at least hints that the problem is with the constructor:
    >> jObject = MyJavaClass();
    No constructor 'MyJavaClass' with matching signature found.
    

    Note that using private constructors is common practice for singleton designs. In such cases we might find a public static class method that returns the class reference (e.g., MyJavaClass.getInstance()).

  9. Non-matching constructor – This is a variation of the previous pitfall. In this case, we try to invoke a class constructor with input parameters that do not match the declaration. A typical example of this is when the constructor is declared to accept an int, and we try to pass a standard Matlab number (which is a double). In such cases, a simple solution could be to either modify the class, overloading the constructor to also accept double, or to type-cast the inputs in Matlab to the relevant type expected by a constructor:
    jObject = MyJavaClass(int32(value));

Any other pitfalls I forgot to mention? Let us know in a comment below.

p.s. – the javaclasspath function has an undocumented input parameter: specifying -v0, -v1 or -v2 sets the Java classloader’s verbosity level to the relevant value. If you don’t know what this means, then you probably don’t need to use this feature…

 
Related posts:
  1. Extending a Java class with UDD Java classes can easily be extended in Matlab, using pure Matlab code. ...
  2. Matlab callbacks for Java events in R2014a R2014a changed the way in which Java objects expose events as Matlab callbacks. ...
  3. The Java import directive The import function can be used to clarify Java code used in Matlab. ...
  4. Matlab callbacks for Java events Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
 

USA visit, 22-31 July 2014

$
0
0

Meet me in MSP, NYC or BOS - 22-31 July 2014I’d like to break the regular flow of technical articles, to announce that I will visit several US cities on July 22-31 to meet some clients for advanced Matlab training and consulting:

  • July 22-24: Minneapolis, MN
  • July 25-27: New York City, NY
  • July 28-31: Boston, MA
  • July 31: New York City, NY

I will be happy to meet you at any of these locations to discuss how I could bring value to your Matlab programming needs, as a consultant, contractor or trainer.

If you would like to schedule a face-to-face meeting, please email me.

 
Related posts:
  1. New York City visit, 21-24 May 2013 I will be visiting New York 21-24 May 2013 to speak at the Matlab Computational Finance Conference. ...
  2. 2013 perspective & plans for 2014 2013 has seen a continued steady growth in website content and readership. This post takes an overview of past achievements and future plans. ...
  3. Advanced Matlab seminars – London, 10-14 March 2014 Advanced Matlab training courses/seminars will be held in London, March 10-14, 2014. Two separate courses will be held: Advanced Matlab Programming – 2 days (March 10-11), including best practices, preparing...
  4. Displaying animated GIFs It is possible to easily display animated images in Matlab figure windows. ...
 

Using pure Java GUI in deployed Matlab apps

$
0
0

I would like to welcome repeat guest blogger Karthik Ponudurai, who has previously written here about the JTattoo look-and-feel, and about integration of Java controls’ events with Matlab callbacks. Today, Karthik discusses a problem when we wish to use pure-Java GUIs in deployed Matlab programs, and the undocumented simple solution.

Reminder: I will be visiting several US cities (Minneapolis, Boston and New York) in July 22-31 (details). Let me know if you’d like to meet me there.

Introduction

Using a pure-Java Swing-based Graphical User Interface (GUI) has several important advantages compared to using a pure-Matlab GUI:

  • Java GUI widget toolkit provides a large collection of components (scrollbar, slider, etc…) and layouts (card, spring, etc…)
  • Multiple event handling options
  • Mature third-party Java Swing IDEs for quick and easy GUI development (Netbeans, Eclipse, etc…)
  • Supports pluggable look and feel that allows applications to have a look and feel that is unrelated to the underlying platform.
  • Java Swing’s window icon can be modified, whereas Mathworks apparently places an [entirely unreasonable] license restriction on modifying the Matlab figure window icon.

When Matlab is in development (non-deployed) mode, we can load and display a Java JFrame using the following Matlab code:

% Add Java library to dynamic Java classpath
javaaddpath([pwd '\ExampleWindow.jar']);
 
% Get example Java window from the library
jFrame = examplewindow.JavaWindow();
 
% Get Java buttons
% Note: see http://UndocumentedMatlab.com/blog/matlab-callbacks-for-java-events-in-r2014a
plotMeshButton = handle(jFrame.getPlotMeshButton(),    'CallbackProperties');
showWarnButton = handle(jFrame.getShowWarnDlgButton(), 'CallbackProperties');
 
% Set Java button callbacks
set(plotMeshButton, 'ActionPerformedCallback', @myPlotMeshCallback);
set(showWarnButton, 'ActionPerformedCallback', @myShowWarnCallback);
 
% Display the Java window
jFrame.setVisible(true);

Java JFrame created in Matlab (click for full-size image)
Java JFrame created in Matlab (click for full-size image)

The problem

All this works great when ran within the Matlab environment. However, when the Matlab source code file (.m) is compiled as a Windows standalone executable application, when running the resulting executable the Java window appears for a short period and then terminates (exits). Without a visible Matlab figure, the compiled Matlab application does not retain the Java window open. The JFrame flashes on for a split-second, and then vanishes.

The solution

To fix this problem, it turns out that we only need to add the Matlab waitfor command after making the Java window visible:

% (earlier code as above)
 
% Display the Java window
jFrame.setVisible(true);
if isdeployed
    waitfor(jFrame);
end

Java JFrame in deployed Matlab (click for full-size image)
Java JFrame in deployed Matlab (click for full-size image)

The waitfor command holds the Java window open, but still enables full interactivity with the window: When a control event is triggered, the specified callback is executed, and then Matlab returns to the waitfor.

A zip file containing the Matlab source-code and its resulting executable can be downloaded from here. You might get a security notification when downloading the zip file, due to the contained exe file. Also note that to run the executable, you need to install Matlab MCR R2012b (8.0) or later, otherwise you will get a run-time error.

Finally, note that closing the Java GUI exits the JVM and by extension the entire containing program (Matlab). Naturally, this has no impact in deployed mode, but to prevent it from exiting the Matlab environment in non-deployed mode, don’t close the Java window by clicking its “X” button etc., but rather by calling jFrame.dispose(); in your Matlab code or the Matlab Desktop’s Command Window.

 
Related posts:
  1. Removing user preferences from deployed apps An unsupported MathWorks Technical Solution explains how to remove private information from deployed (compiled) matlab applications. ...
  2. Disabling menu entries in deployed docked figures Matlab's standard menu items can and should be removed from deployed docked figures. This article explains how. ...
  3. Speeding up compiled apps startup The MCR_CACHE_ROOT environment variable can reportedly help to speed-up deployed Matlab executables....
  4. Matlab-Java interface using a static control The switchyard function design pattern can be very useful when setting Matlab callbacks to Java GUI controls. This article explains why and how....
 

Class object tab completion & improper field names

$
0
0

I recently consulted to a very large industrial client. Following a merger/acquisition, the relevant R&D department had two development groups using different technologies: one group uses Matlab, the other does not. My client wanted both groups to use Matlab, something that would naturally please MathWorks.

Unfortunately, it turns out that a technical challenge was preventing this move: the other technology enabled data field names (identifiers) longer than Matlab’s namelengthmax=63 characters, and these names also sometimes contained illegal identifier characters, such as spaces or symbols. This prevented an easy code transition, indefinitely delaying the migration to Matlab.

Accessing improper fieldnames

I suggested to this client to use Matlab class objects that overloaded the subsref() and subsasgn() methods: the long original identifiers would be stored in some internal container (cell array or containers.Map etc.), and they would be accessed not directly (which would be impossible since they are not valid Matlab identifiers) but via the overloaded methods. Something along the following lines:

classdef ExtendedFieldsClass
    % The internal data implementation is not publicly exposed
    properties (Access = 'protected')
        props = containers.Map;
    end
 
    methods (Access = 'public', Hidden=true)
 
        % Overload property assignment
        function obj = subsasgn(obj, subStruct, value)
            if strcmp(subStruct.type,'.')
                try
                    obj.props(subStruct.subs) = value;
                catch
                    error('Could not assign "%s" property value', subStruct.subs);
                end
            else  % '()' or '{}'
                error('not supported');
            end
        end
 
        % Overload property retrieval (referencing)
        function value = subsref(obj, subStruct)
            if strcmp(subStruct.type,'.')
                try
                    value = obj.props(subStruct.subs);
                catch
                    error('"%s" is not defined as a property', subStruct.subs);
                end
            else  % '()' or '{}'
                error('not supported');
            end
        end
    end
end

This works splendidly, as the following snippet shows:

>> c = ExtendedFieldsClass
c =
  ExtendedFieldsClass with no properties.
 
>> c.(' asd f @#$^$%&') = -13.5;  % no error
 
>> c.(' asd f @#$^$%&')
ans =
                     -13.5
 
>> c.(' asd f @#$^$%& xyz')  % note the extra "xyz"
Error using ExtendedFieldsClass/subsref (line 27)
" asd f @#$^$%& xyz" is not defined as a property

Note how we need to use the () parentheses in order to access the “properties” as dynamic fieldnames. We would naturally get an error if we tried to directly access the field:

>> c. asd f @#$^$%&
 c. asd f @#$^$%&
        |
Error: Unexpected MATLAB expression.

Tab completion

So far so good.

The problem is that we would also like to see the defined “properties” when in the desktop’s tab completion. i.e., when I type “c.” and then click <tab> in the Matlab command prompt, I’d like to see the list of defined “properties” in a tooltip (in the example above: ” asd f @#$^$%&”). Instead, I get the message “No Completions Found.”:

Missing tab completion

Missing tab completion

I described the hack for desktop tab-completion a few years ago. Unfortunately, that hack only works for functions. We need to find another solution for Matlab class objects.

The solution is to overload the fieldnames() function as well, such that it would return a cell-array of the relevant strings:

classdef ExtendedFieldsClass
    % The internal data implementation is not publicly exposed
    properties (Access = 'protected')
        props = containers.Map;
    end
 
    methods (Access = 'public', Hidden=true)
 
        % Overload property assignment
        function obj = subsasgn(obj, subStruct, value)
            ...  (as above)
        end
 
        % Overload property retrieval (referencing)
        function value = subsref(obj, subStruct)
            ...  (as above)
        end
 
        % Overload fieldnames retrieval
        function names = fieldnames(obj)            names = sort(obj.props.keys);  % return in sorted order        end    end
end

When we now run this in the command prompt, we get the expected behavior:

Working tab completion

Working tab completion

R2014a

Unfortunately, this works only up to and including Matlab release R2013b. In R2014a, MathWorks made some internal change that prevents overloading the fieldnames function. To be more precise, we can still overload it as above, and it will indeed work if we directly call fieldnames(c), but it no longer has any effect on the tab completion. On R2014a, the tab-completion remains broken and returns “No Completions Found.” When this was reported to MathWorks some time ago, the official response was that the previous behavior was considered a “bug”, and this was “fixed” in R2014a (don’t bother searching for it in the official bugs parade). Go figure…

So what do you think I should now do? Remember: this is a large client, who knows how many licenses are at stake. Should I suggest to my client not to switch to Matlab? Or should I suggest that they keep using R2013b across the entire organization and cancel their annual maintenance? Or maybe I should simply tell them to accept the fact that some important functionality should be expected to get broken whenever Matlab is upgraded?

I really want my client to switch to Matlab across the board. After all, as a Matlab consultant/trainer I directly benefit from a larger Matlab client-base. But these sort of things just blow me away. Sometimes I feel as if I am swimming against the current, and that’s frustrating. I admit it doesn’t happen very often. Then again, I guess if things were straight-forward, nobody would need me to consult them…

Don’t mind me – just blowing off some steam. I’m allowed to, every now and then, aren’t I? :-)

Michal Kutil described a mechanism for overloading the methods function, which is also part of the tab-completion tooltip. The problem here is that we cannot simply overload methods in our class, since Matlab calls methods with the class name (not the class object reference) when it wants to determine the relevant methods to display in the tooltip. Michal’s solution was to create a wrapper function that calls the overloaded variant. This wrapper function can then be placed within a @char folder somewhere in the Matlab path. I used a similar trick for my profile_history utility last month.

Related newsgroup posts by Eric Salemi here and here.

Similarly, in order to overload the data-value tooltip (when hovering over the object in the editor), or when displaying the object in the Matlab command prompt, simply overload the disp() function (see related) – luckily, this still works in R2014a (I hope MathWorks won’t “fix” this “bug” in R2014b or whenever):

        % Overload class object display
        function disp(obj)
            disp([obj.props.keys', obj.props.values']);  % display as a cell-array
        end

This blog will now take a short vacation for a few weeks, due to my U.S. trip. I will return with some fresh material in August – stay tuned!

 
Related posts:
  1. Class object creation performance Performance aspects of Matlab class object creation are discussed, with specific suggestions. ...
  2. Setting class property types Matlab's class properties have a simple and effective mechanism for setting their type....
  3. getundoc – get undocumented object properties getundoc is a very simple utility that displays the hidden (undocumented) properties of a specified handle object....
  4. Accessing private object properties Private properties of Matlab class objects can be accessed (read and write) using some undocumented techniques. ...
 

Online (web-based) Matlab

$
0
0

For many years I searched for a good solution for deploying Matlab applications in online web-pages. There used to be a solution over a decade ago but it was taken off the market. We could use the Java Builder to wrap our Matlab apps in a JAR that could be called by a Java-based application server, but we’d still need to develop the front-end web GUI as well as the middle-tier plumbing. A similar limitation exists if we wish to use the new Matlab Production Server (MSP). Developing this front-end and middle-tier is by no means a trivial exercise, as much as MathWorks presentations would like it to appear. Not to mention the fact that the Builder and the MSP are relatively costly (~$5-7K and ~$30K respectively).

I was thrilled to see the answer in the recent Matlab Computational Finance Conference, London. I presented at last year’s conference, so I was excited to review this year’s presentations when I came across a nugget in Kevin Shea’s keynote presentation on new Matlab developments. Note that there were two separate Matlab computational-finance events in 2014 – in London (June 24) and NY (April 9); the interesting piece is from London. Unlike the NY conference, the London conference proceedings do not include a video recording, only the slides (perhaps the video will be added to the proceedings page later, after all it takes some time to process). The last slide of Kevin’s presentation shows a screenshot of a Chrome browser displaying what appears to be a full-fledged Matlab desktop (Workspace, Editor, Command Window, figures) at https://matlab.mathworks.com:

Matlab Online (click to zoom)
Matlab Online (click to zoom)

The benefits of using Matlab Online are potentially tremendous: excluding some limitations (e.g., limited GUI, run time and supported toolboxes), we could deploy our Matlab programs online with minimal to no additional dev effort.

Information on Matlab Online can be found at http://mathworks.com/products/matlab/online. It even includes detailed dedicated documentation for all the supported functions and features.

For some reason, MathWorks has chosen not to link this new (and in my humble opinion, great) product in its official list of products. Perhaps the reason is that MathWorks do not wish for Matlab Online to cannibalize its main offerings. This might also explain the limitations placed on the online version (some limitations are technical, the rest are business-related). Matlab Online requires a dedicated login access, provided by MathWorks. Unfortunately, it is still not fully released to the public and is only available to users with up to date student licenses.

Still, if you are an important enough client of MathWorks, you might ask for access. Even with its current limitations, Matlab Online may well be useful for your needs. If you press strongly enough, and if your account is large enough, perhaps MathWorks might even enable a dedicated subdomain for you (as in intel.mathworks.com or matlab.apple.com).

Here’s another screenshot, in case you’re not convinced yet:

Matlab Online (click to zoom)
Matlab Online (click to zoom)

A post by MathWorks on the Answers forum earlier this year lists Matlab Online along with some additional online-computing alternatives for Matlab.

And now for some guesswork/speculation: MathWorks placed a major bet on Java technology in the early 2000′s (actually the late 90′s, since R12 took a few years to develop). Java was indeed hot at that time, but then so were some other technologies over the years. Fortunately for MathWorks, Java proved agile, mature and portable enough to enable mobile and online porting. This could explain the lack of Simulink GUI support, since Simulink GUI is still C++-based to a large extent. It might also explain the extra work done in HG2 in the graphic infrastructure (previously C++-based). After all, the basic MCOS graphic classes were available years ago, so if HG2 was only about a transition from double-value handles to MCOS, and some nice beautifications (anti-aliasing, CVD-aware colors etc.) then HG2 could be released long ago. Working on the underlying engine to make it portable could well explain HG2′s belated arrival.

So what does all this mean about Matlab’s future? Well, it appears to me that MathWorks’ apparent move towards SaaS (software as a service) and cloud-based computing is slightly belated, but quite evidently follows a general industry trend. In my eyes it heralds a move by MathWorks from desktop to online services, perhaps even to pay-per-use computing (as by Techila for example). The Matlab desktop will still be MathWorks’ bread and butter for many years to come. But the ability of Matlab programs to work either locally (on a Matlab client, either thin or thick) or online would be an enormous productivity benefit, in essence being a “killer feature” over Matlab’s competitors.

Technically, Matlab’s online integration could enable closer integration of online content in Matlab programs (esp. GUI). I’ve already shown how active web content can be displayed in Matlab GUI, but a closer integration could mean this might all become fully documented and integrated (recall Windows’ failed Active Desktop on one hand, but smart-phones’ enormously-successful active widgets on the other). It could also enable closer integration with online graphing services such as Plotly.

I for one, can’t wait to see this dream being realized. It’s not too far down the road, it would seem. I just hope that licensing and cost considerations won’t keep us from using it. MathWork’s recent Home License scheme seems to indicate that this is well understood by MathWorks, so I am highly optimistic :-)

Then again, all this might be pure baseless speculation. Time will tell.

 
Related posts:
  1. Changes in the online doc URLs Matlab release R2012b has broken a vast number of links to its online documentation pages. ...
  2. Types of undocumented Matlab aspects This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
  3. Matlab installation take 2 A list of suggested config changes to the default Matlab installation is detailed. ...
  4. JGit-Matlab integration JGit source-control integration package can easily be integrated in Matlab. ...
 

Property value change listeners

$
0
0

For performance reasons, it is almost always better to respond to events (asynchronously), than to continuously check a property value (synchronous polling). Therefore, if we wish to do something when some property value is changed (e.g., log the event, shut down the system, liquidate the portfolio, call the police, …), then it is preferable to attach a property-change listener callback.

The standard (documented) way of attaching a value-change listener to Matlab class properties is via the addlistener function. This only works for handle (not value) classes, and only to those properties that have the SetObservable and/or GetObservable attribute turned on:

addlistener(hClassObject, propertyName, 'PostSet', @myCallbackFcn);

This is all nice and well for Matlab class properties, but what about HG (handle Graphics: plots & GUI) properties? Can we similarly listen to changes in (say) the axes limits? Until now this has been possible, but undocumented. For example, this will trigger myCallbackFcn(hAxes,eventData) whenever the axes limits change (due to zoom, pan, plotting etc.):

addlistener(gca, 'YLim', 'PostSet', @(hAxes,eventData) myCallbackFcn(hAxes,eventData));
 
% Or (shorter equivalent):
addlistener(gca, 'YLim', 'PostSet', @myCallbackFcn);

This could be very useful when such properties could be modified from numerous different locations. Rather than updating all these location to call the relevant callback function directly, we simply attach the callback to the property-change listener. It could also be useful in cases where for some reason we cannot modify the source of the update (e.g., third-party or legacy code).

In addition to PostSet, we could also set listeners for PreSet. Also, we could set listeners on PostGet and PreGet – this could be useful for calculating dynamic (dependent) property values.

Under the hood

The HG1 variant of addlistener is basically equivalent to the following low-level UDD-based code snippet, as explained here:

% Create the listener object
hAxes = handle(gca);  % a UDD axes class object
hProp = findprop(hAxes,'YLim');  % a schema.prop class object
hListener = handle.listener(hAxes, hProp, 'PropertyPostSet', @myCallbackFcn);
 
% persist the listener in memory for as long as the source object (hAxes) is alive
setappdata(hAxes, 'listener__', hListener);

(in old Matlab releases, addlistener was a regular m-function that placed the listeners in the source handle’s ApplicationData property, as the code above shows; newer releases reimplemented addlistener as an internal built-in function and the listener is now stored somewhere in the DLL’s inaccessible memory, rather than in the ApplicationData property)

In HG2, handle.listener no longer works. Fortunately, we don’t need it since we have addlistener that works the same way for both HG1 (UDD objects) and HG2 (MCOS objects). Kudos on the backward-compatibility aspect, MathWorks!

 
Related posts:
  1. UDD Events and Listeners UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
  2. Getting default HG property values Matlab has documented how to modify default property values, but not how to get the full list of current defaults. This article explains how to do this. ...
  3. xlsread functionality change in R2012a The functionality of the xlsread function has changed without documentation or warning in the R2012a release. ...
  4. JIDE Property Grids The JIDE components pre-bundled in Matlab enable creating user-customized property grid tables...
 

Inter-Matlab data transfer with memcached

$
0
0

Once again I welcome guest blogger Mark Mikofski. Mark has written here last year about JGIT-Matlab integration and earlier this year on JSON-Matlab integration. Today, Mark shows how to use the well-known open-source memcached library for data transfer between separate Matlab processes. Readers are also referred to Mark’s article on his blog. I have already written about various ways to communicate between separate Matlab processes – today’s article is an important complement to these methods.

Downloads

Stringpool's memcached tutorialThe memcached open-source library is great for sending objects from process to process. It is typically used to cache large data objects from databases or in a distributed environment, but we can also use it as a simple distributed shared memory system, which stores data in key-value pairs (as in a hashtable).

I was able to use memcached to set and retrieve objects from two different instances of Matlab. Both the Java and .NET variants of memcached can be used for this. memcached requires two components: server and client: The server comes precompiled, while the client needs to be compiled by us.

The memcached server was compiled by Trond Norbye from Couchbase (previously Membase and Northscale) for 32-bit and 64-bit Windows OS. See below how to run it as a service using the Python PyWin32 package.

I compiled Windows binaries of memcached-client libraries for both the Java and .NET using Java-1.7 and Visual Studio 2010 and zipped them up here.

Note: additional (non-memcached) shared-memory implementations used in Matlab include Joshua Dillon’s sharedmatrix (also see here), and Kevin Stone’s SharedMemory utilities, which use POSIX shared-memory and the Boost IPC library. Rice University’s TreadMarks library is another example of a shared-memory approach that has been used with Matlab, in the MATmarks package (note that the current availability of MATmarks is unclear).

.NET

We use the Memcached server version 1.4.5 patched for 64-bit Windows, precompiled by Trond Norbye from Couchbase (previously Membase and Northscale).

For the Memcached .NET client, download the Memcached.ClientLibrary port of com.meetup.memcached from SourceForge, and then compile using Microsoft Visual Studio 2010 C#, Release/AnyCPU configuration. Since the original project files were for MSVC-8, MSVC-10 starts a conversion wizard that first backed up the previous project files and then creates a new MSVC-10 project, including a new solution file. I then build the clientlib_2.0 project from the MSVC-10 IDE GUI using “build” from the menu, and voila: I got a new DLL.

Usage in Matlab is as follows:

  1. Start the memcached server:
    C:\> C:\path\to\memcached.exe -vv
  2. Do this on both MATLAB instances:
    asm = NET.addAssembly('C:\full\path\to\Memcached.ClientLibrary.dll');
    pool = Memcached.ClientLibrary.SockIOPool.GetInstance();
    pool.SetServers({'127.0.0.1:11211'});
    pool.Initialize;
    mc = Memcached.ClientLibrary.MemcachedClient();
  3. On MATLAB instance #1:
    mc.Set('name','mark')
  4. On MATLAB instance #2:
    >> myName = mc.Get('name')
    myName = 
    mark

Java

MATLAB and memcached also works perfectly with the original meetup.com Java version that the .NET version was ported from. The commands are exactly the same, but the Apache logger is not cleaned up for the non-bench/test sources (with isErrorEnabled(), etc. see jlog4 documentaion), so you always get this error message:

log4j:WARN No appenders could be found for logger (com.meetup.memcached.SockIOPool).
log4j:WARN Please initialize the log4j system properly.

Because there are log calls in the MemcachedClient and SockIOPool files that never have BasicConfiguration.configure() or set any jlog4. like the appender hence the error. Of course they never meant for log messages to be displayed when deployed, so wrapping with isErrorEnabled() like the .NET version does would be better.

The Java package is called com.meetup.memcached. We should build it ourselves from the Github source. The jar from the Maven repository didn’t work (attempting to start the sock I/O pool raised several Java errors due to missing includes), and differs a bit from the GitHub repo.

$ /c/Program\ Files/Java/jdk1.7.0_55/bin/javac.exe -verbose -classpath ../lib/log4j.jar -sourcepath com/meetup/memcached/ -source 1.6 -target 1.6 -d ../bin/ com/meetup/memcached/*.java
$ /c/Program\ Files/Java/jdk1.7.0_55/bin/jar.exe -cvf MeetupMemcached.jar com/

To use in Matlab, first, start the memcached server, then start sock I/O pools and memcached clients on both Matlab instances:

>> javaaddpath('C:\full\path\to\MeetupMemcached.jar');
>> pool = com.meetup.memcached.SockIOPool.getInstance();
>> pool.setServers({'127.0.0.1:11211'});
>> pool.initialize;
>> mc = com.meetup.memcached.MemcachedClient;
>> mc.set('name','mark'); % on 1st instance/process
>> myName = mc.get('name') % on 2nd instance/process
myName = 
mark

Other clients

  • xmemcached – Github:killme2008, Google Code project and Maven repo
  • The Xmemcached client works well. It is the most recently updated. There are jar files on the releases page of the GitHub repo. Here is an example from the 2.0.0 release from this April. The example is from the google.code wiki User Guide in English.

    >> javaaddpath('C:\full\path\to\xmemcached-2.0.0.jar');
    >> addr = net.rubyeye.xmemcached.utils.AddrUtil.getAddresses('localhost:11211')
    addr =
    [localhost/127.0.0.1:11211]
    >> builder = net.rubyeye.xmemcached.XMemcachedClientBuilder(addr)
    builder =
    net.rubyeye.xmemcached.XMemcachedClientBuilder@7ef6a26
    >> mc = builder.build()
    log4j:WARN No appenders could be found for logger (net.rubyeye.xmemcached.XMemcachedClient).
    log4j:WARN Please initialize the log4j system properly. 
    mc = 
    net.rubyeye.xmemcached.XMemcachedClient@275e6ce5
    >> mc.set('name',0,'mark')
    ans =
         1
    >> myName = mc.get('name')
    myName =
    mark
  • Enyim – NuGet and Github:enyim
    I couldn’t get this assembly to load as built, I always got an “Strong Name Validation Failed” error, perhaps because I am on a 64-bit machine, but using MSVC express.
  • spymemcached – Github:dustin, Google Code project and Maven repo
    I also couldn’t get this to work. Even though I could make an array of Java socket objects using InetSocket the connection was always refused even though the memcached server was operating on the specified port.

memcached server as Windows service

This Gist uses Python PyWin32 win32service to install, remove, configure, start and stop the memcached server.

 
Related posts:
  1. Serializing/deserializing Matlab data Matlab does not provide a documented manner to serialize data into a byte stream, but we can do this with some undocumented functionality. ...
  2. Accessing plot brushed data Plot data brushing can be accessed programmatically using very simple pure-Matlab code...
  3. Draggable plot data-tips Matlab's standard plot data-tips can be customized to enable dragging, without being limitted to be adjacent to their data-point. ...
  4. Editbox data input validation Undocumented features of Matlab editbox uicontrols enable immediate user-input data validation...
 

savezip utility

$
0
0

A few months ago I wrote about Matlab’s undocumented serialization/deserialization functions, getByteStreamFromArray and getArrayFromByteStream. This could be very useful for both sending Matlab data across a network (thus avoiding the need to use a shared file), as well as for much faster data-save using the -V6 MAT format (save -v6 …).

As a followup to that article, in some cases it might be useful to use ZIP/GZIP compression, rather than Matlab’s proprietary MAT format or an uncompressed byte-stream.

Unfortunately, Matlab’s compression functions zip, gzip and tar do not really help run-time performance, but rather hurt it. The reason is that we would be paying the I/O costs three times: first to write the original (uncompressed) file, then to have zip or its counterparts read it, and finally to save the compressed file. tar is worst in this respect, since it does both a GZIP compression and a simple tar concatenation to get a standard tar.gz file. Using zip/gzip/tar only makes sense if we need to pass the data file to some external program on some remote server, whereby compressing the file could save transfer time. But as far as our Matlab program’s performance is concerned, these functions bring little value.

In contrast to file-system compression, which is what zip/gzip/tar do, on-the-fly (memory) compression makes more sense and can indeed help performance. In this case, we are compressing the data in memory, and directly saving to file the resulting (compressed) binary data. The following example compresses int8 data, such as the output of our getByteStreamFromArray serialization:

% Serialize the data into a 1D array of uint8 bytes
dataInBytes = getByteStreamFromArray(data);
 
% Parse the requested output filename (full path name)
[fpath,fname,fext] = fileparts(filepath);
 
% Compress in memory and save to the requested file in ZIP format
fos = java.io.FileOutputStream(filepath);
%fos = java.io.BufferedOutputStream(fos, 8*1024);  % not really important (*ZipOutputStream are already buffered), but doesn't hurt
if strcmpi(fext,'.gz')
    % Gzip variant:
    zos = java.util.zip.GZIPOutputStream(fos);  % note the capitalization
else
    % Zip variant:
    zos = java.util.zip.ZipOutputStream(fos);  % or: org.apache.tools.zip.ZipOutputStream as used by Matlab's zip.m
    ze  = java.util.zip.ZipEntry('data.dat');  % or: org.apache.tools.zip.ZipEntry as used by Matlab's zip.m
    ze.setSize(originalDataSizeInBytes);
    zos.setLevel(9);  % set the compression level (0=none, 9=max)
    zos.putNextEntry(ze);
end
zos.write(dataInBytes, 0, numel(dataInBytes));
zos.finish;
zos.close;

This will directly create a zip archive file in the current folder. The archive will contain a single entry (data.dat) that contains our original data. Note that data.dat is entirely virtual: it was never actually created, saving us its associated I/O costs. In fact we could have called it simply data, or whatever other valid file name.

Saving to a gzip file is even simpler, since GZIP files have single file entries. There is no use for a ZipEntry as in zip archives that may contain multiple file entries.

Note that while the resulting ZIP/GZIP file is often smaller in size than the corresponding MAT file generated by Matlab’s save, it is not necessarily faster. In fact, except on slow disks or network drives, save may well outperform this mechanism. However, in some cases, the reduced file size may save enough I/O to offset the extra processing time. Moreover, GZIP is typically much faster than either ZIP or Matlab’s save.

Loading data from ZIP/GZIP

Similar logic applies to reading compressed data: We could indeed use unzip/gunzip/untar, but these would increase the I/O costs by reading the compressed file, saving the uncompressed version, and then reading that uncompressed file into Matlab.

A better solution would be to read the compressed file directly into Matlab. Unfortunately, the corresponding input-stream classes do not have a read() method that returns a byte array. We therefore use a small hack to copy the input stream into a ByteArrayOutputStream, using Matlab’s own stream-copier class that is used within all of Matlab’s compression and decompression functions:

% Parse the requested output filename (full path name)
[fpath,fname,fext] = fileparts(filepath);
 
% Get the serialized data
streamCopier = com.mathworks.mlwidgets.io.InterruptibleStreamCopier.getInterruptibleStreamCopier;
baos = java.io.ByteArrayOutputStream;
fis  = java.io.FileInputStream(filepath);
if strcmpi(fext,'.gz')
    % Gzip variant:
    zis  = java.util.zip.GZIPInputStream(fis);
else
    % Zip variant:
    zis  = java.util.zip.ZipInputStream(fis);
    % Note: although the ze & fileName variables are unused in the Matlab
    % ^^^^  code below, they are essential in order to read the ZIP!
    ze = zis.getNextEntry;
    fileName = char(ze.getName);  %#ok<NASGU> => 'data.dat' (virtual data file)
end
streamCopier.copyStream(zis,baos);
fis.close;
data = baos.toByteArray;  % array of Matlab int8
 
% Deserialize the data back into the original Matlab data format
% Note: the zipped data is int8 => need to convert into uint8:
% Note2: see discussion with Martin in the comments section below
if numel(data) < 1e5
    data = uint8(mod(int16(data),256))';
else
    data = typecast(data, 'uint8');
end
 
data = getArrayFromByteStream(data);

Note that when we deserialize, we have to convert the unzipped int8 byte-stream into a uint8 byte-stream that getArrayFromByteStream can process (we don’t need to do this during serialization).

The SAVEZIP utility

I have uploaded a utility called SAVEZIP to the Matlab File Exchange which includes the savezip and loadzip functions. These include the code above, plus some extra sanity checks and data processing. Usage is quite simple:

savezip('myData', magic(4))   %save data to myData.zip in current folder
savezip('myData', 'myVar')    %save myVar to myData.zip in current folder
savezip('myData.gz', 'myVar') %save data to myData.gz in current folder
savezip('data\myData', magic(4))    %save data to .\data\myData.zip
savezip('data\myData.gz', magic(4)) %save data to .\data\myData.gz
 
myData = loadzip('myData');
myData = loadzip('myData.zip');
myData = loadzip('data\myData');
myData = loadzip('data\myData.gz');

Jan Berling has written another variant of the idea of using getByteStreamFromArray and getArrayFromByteStream for saving/loading data from disk, in this case in an uncompressed manner. He put it all in his Bytestream Save Toolbox on the File Exchange.

Transmitting compressed data via the network

If instead of saving to a file we wish to transmit the compressed data to a remote process (or to save it ourselves later), we can simply wrap our ZipOutputStream with a ByteArrayOutputStream rather than a FileOutputStream. For example, on the way out:

baos = java.io.ByteArrayOutputStream;
if isGzipVarant
    zos = java.util.zip.GZIPOutputStream(baos);
else  % Zip variant
    zos = java.util.zip.ZipOutputStream(baos);
    ze  = java.util.zip.ZipEntry('data.dat');
    ze.setSize(numel(data));
    zos.setLevel(9);
    zos.putNextEntry(ze);
end
dataInBytes = int8(data);  % or: getByteStreamFromArray(data)
zos.write(dataInBytes,0,numel(dataInBytes));
zos.finish;
zos.close;
compressedDataArray = baos.toByteArray;  % array of Matlab int8

I leave it as an exercise to the reader to make the corresponding changes for the receiving end.

New introductory Matlab book

Matlab has a plethora of introductory books. But I have a special affection to one that was released only a few days ago: MATLAB Succinctly by Dmitri Nesteruk, for which I was a technical editor/reviewer. It’s a very readable and easy-to-follow book, and it’s totally free, so go ahead and download.

MATLAB Succinctly book by Dmitri Nesteruk This title adds to the large (and growing) set of free ~100-page introductory titles by Syncfusion, on a wide variety of programming languages and technologies. Go ahead and download these books as well. While you’re at it, take a look at Syncfusion’s set of professional components and spread the word. If Syncfusion gets enough income from such incoming traffic, they may continue to support their commendable project of similar free IT-related titles.

This may be a good place to update that my own [second] book, Accelerating MATLAB Performance, is nearing completing, and is currently in advanced copy-editing stage. It turned out that there was a lot more to Matlab performance than I initially realized. The book size (and writing time) doubled, and it turned out to be a hefty ~750 pages packed full with performance improvement tips. I’m still considering the cover image (ideas anyone?) and working on the index, but the end is now in sight. The book should be in your favorite bookstore this December. If you can’t wait until then, and/or if you’d rather use the real McCoy, consider inviting me for a consulting session…

 
Related posts:
  1. ScreenCapture utility The ScreenCapture utility uses purely-documented Matlab for capturing a screen region as an image from within Matlab. ...
  2. An interesting uitree utility ExploreStruct is a utility that shows how custom uitrees can be integrated in Matlab GUI...
  3. Serializing/deserializing Matlab data Matlab does not provide a documented manner to serialize data into a byte stream, but we can do this with some undocumented functionality. ...
  4. Matlab callbacks for Java events Events raised in Java code can be caught and handled in Matlab callback functions - this article explains how...
 

CheckboxList

$
0
0

Several years ago I blogged about using a checkbox-tree in Matlab. A few days ago there was a question on the Matlab Answers forum asking whether something similar can be done with Matlab listboxes, i.e. add checkboxes next to each list item. There are actually several alternatives for this and I thought this could be a good opportunity to discuss them:

MathWorks CheckBoxList

MathWorks CheckBoxList


The HTML image variant

The simplest alternative is to use small icon images checked and unchecked as part of the listbox item labels. As I explained last year, listboxes (like all other Matlab uicontrols that rely on underlying Java Swing components), support HTML and can be formatted using HTML images. For example:

Matlab listbox with HTML image icons

Matlab listbox with HTML image icons

In order to check/uncheck items in the listbox, we can trap the underlying Java component’s MouseClickedCallback using the findjobj utility:

% Assume checked.gif, unchecked.gif are 16x16 icons
prefix = ['<html><img src="file:///' strrep(path_of_icon_files),'\','/') '/unchecked.gif" height=16 width=16 />'];
sampleData = strcat(prefix, {'first', 'Second', 'Third', 'and last'});  % all items are unchecked at first
hListbox = uicontrol(...);
jScrollPane = findjobj(hListbox);
jListbox = handle(jScrollPane.getViewport.getView, 'CallbackProperties');
jListbox.MouseClickedCallback = {@mouseClickedFcn,hListbox};
 
function mouseClickedFcn(jListbox, jEventData, hListbox)
   % Get the clicked item and row index
   clickedX = jEventData.getX;
   clickedY = jEventData.getY;
   if clickedX > 15,  return;  end  % did not click a checkbox so bail out
   clickedRow = jListbox.locationToIndex(java.awt.Point(clickedX,clickedY)) + 1;  % Matlab row index = Java row index+1
   if clickedRow <= 0,  return;  end  % clicked not on an item - bail out
   strs = get(hListbox,'String');
   clickedItem = strs{clickedRow};
 
   % Switch the icon between checked.gif <=> unchecked.gif
   if strfind(clickedItem,'unchecked')
       strs{clickedRow} = strrep(clickedItem,'unchecked','checked');
   else
       strs{clickedRow} = strrep(clickedItem,'checked','unchecked');
   end
   set(hListbox,'String',strs);  % update the list item
end

Finally, when we process the selected list item(s), we can simply check whether they contain ‘unchecked.gif’ or ‘checked.gif’. Pretty straight-forward stuff.

MathWorks CheckBoxList

com.mathworks.mwswing.checkboxlist.CheckBoxList is a JList extension that displays a list of labels in a list with a checkbox next to each label. The labels’ checkboxes can be set, unset and queried using methods supplied by the CheckBoxList class or its com.mathworks.mwswing.checkboxlist.DefaultListCheckModel model:

% First create the data model
jList = java.util.ArrayList;  % any java.util.List will be ok
jList.add(0,'First');
jList.add(1,'Second');
jList.add(2,'Third');
jList.add(3,'and last');
 
% Next prepare a CheckBoxList component within a scroll-pane
jCBList = com.mathworks.mwswing.checkboxlist.CheckBoxList(jList);
jScrollPane = com.mathworks.mwswing.MJScrollPane(jCBList);
 
% Now place this scroll-pane within a Matlab container (figure or panel)
[jhScroll,hContainer] = javacomponent(jScrollPane,[10,10,80,65],gcf);
 
% Set the listbox to respond to click events
jhCBList = handle(jCBList, 'CallbackProperties');
set(jhCBList, 'ValueChangedCallback', @myMatlabCallbackFcn);
 
% Update some items' state programmatically
jCBModel = jCBList.getCheckModel;
jCBModel.checkAll;
jCBModel.uncheckIndex(1);
jCBModel.uncheckIndex(3);

This results in the following image:

MathWorks CheckBoxList

MathWorks CheckBoxList

We can query the various checked/unchecked states programmatically:

>> jCBList.getCheckedValues
ans =
[First, Third]
 
>> jCBList.getCheckedIndicies'
ans =
           0       2
 
>> jCBModel.isIndexChecked(0)
ans =
     1    % =true

JIDE’s CheckBoxList

There is also an unrelated JIDE equivalent: com.jidesoft.swing.CheckBoxList. Readers are referred to the JIDE documentation for additional details.

The basic idea is the same as with the MathWorks CheckBoxList: we create the data model, then create a CheckBoxList component within a JScrollPane and place this onscreen using the javacomponent function. We can then modify or query the data model programmatically, and set various callback functions to process user events.

% Prepare the data model as above
 
% Now display onscreen:
jCBList = com.jidesoft.swing.CheckBoxList(jList.toArray)
jScrollPane = com.mathworks.mwswing.MJScrollPane(jCBList);
[jhScroll,hContainer] = javacomponent(jScrollPane, [120,10,80,65], gcf);
 
% Do some programmatic updates:
jCBList.selectAll;  % reverse: jCBList.selectNone
jCBList.setCheckBoxListSelectedIndices([0,2]);

The appearance is very similar to the MathWorks CheckBoxList, except that JIDE’s CheckBoxList has slightly less space between the list rows, and between the checkboxes and labels. The main difference between these components is not in their visual appearance but rather in their supported functionalities (internal methods) – some people might prefer the MathWorks component, others might like JIDE better. To see these functionalities, use my uiinspect and/or checkClass utilities.

For additional information on the MathWorks and JIDE components, and how to investigate and customize them, see Chapter 5 of my Matlab-Java programming book.

ActiveX and other alternatives

If you are running on Windows, you could use ActiveX controls that implement checkbox list functionality. One such control that is pretty standard is Microsoft’s MSComctlLib.ListViewCtrl.2. I showed an example of ListViewCtrl usage a few years ago, and readers are referred there for details. Here is the end result:

Sorted ListViewCtrl

Sorted ListViewCtrl

Granted, this is more of a table having a checkbox column than a listbox, but you can easily make the ListViewCtrl have only a single column.

In addition to this standard ListViewCtrl control, there are plenty of other third-party ActiveX or Java controls that can more-or-less easily be integrated in our Matlab GUI. The drawback of ActiveX is that it only works on a limited set of platforms, whereas the Java-based components (either MathWorks or JIDE) work on all Matlab installations.

Anyway, don’t let anyone say ever again that Matlab GUI is boring. It is not. It is only limited by our imagination and our willingness to find and customize components that implement our requirements. There are plenty of alternatives out there, we just need to reach out and use them. If you can’t do it yourself, you could always use an external consultant like me to help you.

 
Related posts:
  1. Customizing listbox & editbox scrollbars Matlab listbox and multi-line editbox uicontrols have pre-configured scrollbars. This article shows how they can be customized....
  2. Tri-state checkbox Matlab checkboxes can easily be made to support tri-state functionality....
  3. Color selection components Matlab has several internal color-selection components that can easily be integrated in Matlab GUI...
  4. Date selection components The JIDE package, pre-bundled in Matlab, contains several GUI controls for selecting dates - this article explains how they can be used...
 

Customizing listbox/combobox items

$
0
0

Last week I wrote about using a variety of techniques to customize listbox items with an attached checkbox icon. Some of these methods used a standard Matlab listbox uicontrol, others used other controls. Today I wish to extend the discussion and show how Matlab listbox and combobox (pop-up) items can be customized in a variety of ways.

To add icons to listbox/combobox items, we could use standard HTML, as I’ve shown last week. This is the simplest method, requires no Java knowledge, and it usually works well. The problem is that when a listbox/combobox has numerous items (hundreds or more), it may start getting sluggish. In such case it is faster to use a dedicated Java cell-renderer that sets the icon, font, colors, tooltip and other aspects on an item-by-item basis. This runs faster and enables far greater customizability than what is possible with HTML. The drawback is that it requires some Java programming. No free lunch…

Listbox and combobox cell-renderers need to extend javax.swing.ListCellRenderer, similarly to uitable cell-renderers. This is basically a simple Java class that minimally contains just an empty constructor and a getListCellRendererComponent() method with a predefined signature. getListCellRendererComponent() is automatically called by the Swing render engine separately for each listbox item, and gets as input args a JList reference, the item value (typically a string), an integer list index, a boolean flag indicating whether the item is currently selected, and another flag indicating whether the item is currently in focus. getListCellRendererComponent() uses these parameters to customize and return a java.awt.Component, which is typically (but not necessarily) a standard Swing JLabel.

Here is a simple example that displays a folder of icon files in a Matlab listbox and combobox. Each item is the filename, with a customization that if the file is an icon, then this icon is displayed next to the file name, otherwise the name appears in red italic without an icon. For illustration, we’ll use Matlab’s builtin icons folder: %matlabroot%/toolbox/matlab/icons/:

Custom listbox cell-renderer    Custom combobox cell-renderer

Creating the cell renderer

We start by creating a custom ListCellRenderer. Place the following code in a file called LabelListBoxRenderer.java:

import java.awt.*;
import javax.swing.*;
import java.util.Hashtable;
 
public class LabelListBoxRenderer extends JLabel implements ListCellRenderer
{
    private String folderPath;
    private final Hashtable<String,ImageIcon> iconsCache = new Hashtable<String,ImageIcon>();
 
    // Class constructors
    public LabelListBoxRenderer() {
        setOpaque(true);
        setHorizontalAlignment(LEFT);
        setVerticalAlignment(CENTER);
    }
    public LabelListBoxRenderer(String folderPath) {
        this();
        this.folderPath = folderPath;
    }
 
    // Return a label displaying both text and image.
    public Component getListCellRendererComponent(
            JList list,
            Object value,
            int index,
            boolean isSelected,
            boolean cellHasFocus)
    {
        String label = value.toString();
        setFont(list.getFont());
        if (isSelected) {
            // Selected cell item
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            // Unselected cell item
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }
        try {
            String iconFname = (folderPath + "/" + label).replace('\\', '/');
            ImageIcon icon = getFileIcon(iconFname);
            setIcon(icon);
            if (icon.getIconWidth() > 0) {
                // Cell item is a valid icon filename
                list.setToolTipText(iconFname + " (" + icon.getIconWidth() + " x " + icon.getIconHeight() + ")");
            } else {
                // Cell item is not an icon filename
                list.setToolTipText(iconFname + " (not an icon)");
                setFont(getFont().deriveFont(Font.ITALIC));
                setForeground(Color.red);
            }
        } catch (Exception e) {
            list.setToolTipText(e.getMessage());
        }
        //System.out.println(index + ": " + label);  // debug console printout
        setText(label);
        return this;
    }
 
    // Modify the folder path (default = current folder)
    public void setFolderPath(String folderPath) {
        this.folderPath = folderPath;
    }
 
    // Lazily load the file icons only as needed, later reuse cached data
    private ImageIcon getFileIcon(String filename) {
        ImageIcon icon;
        if (iconsCache.containsKey(filename)) {
            // Reuse cached data
            icon = iconsCache.get(filename);
        } else {
            // Lazily load the file icons only as needed
            icon = new ImageIcon(filename);
            iconsCache.put(filename, icon);  // store in cache for later use
        }
        return icon;
    }
}

In the code above, I’ve cached the ImageIcons, so that the actual disk file is only accessed once rather than repeatedly whenever the cell needs to be rendered. For even improved performance, we could also cache the tooltips and derived italic font so that they would not be regenerated each time (note that the list’s font is not the same as the cell component’s font) – I will leave this as an exercise to the reader.

Next, compile this file (using the standard javac compiler or any Java IDE), ensuring that you target a JVM compatible with your Matlab (JVM 5 will work on R14SP2 onward, 6 on R2007b onward, and 7 only on R2013b or newer). For convenience, both the source and compiled files for the LabelListBoxRenderer class can be downloaded here: LabelListBoxRenderer.java, LabelListBoxRenderer.class.

Using the cell-renderer in Matlab listboxes

Now that we have a custom cell renderer, we should add the LabelListBoxRenderer.class file to Matlab’s Java classpath using the javaaddpath function and then use this class in Matlab:

% Create the Matlab listbox
iconsFolder = fullfile(matlabroot, 'toolbox/matlab/icons');
files = dir(iconsFolder);
hListbox = uicontrol('Style','list', 'String',{files.name}, 'Position',[10,10,120,150]);
 
% Find the uicontrol's underlying Java component
jScroll = findjobj(hListbox);
jListbox = jScroll.getViewport.getView;
 
% Update the listbox's cell-renderer
javaaddpath 'C:\Yair\Undocumented Matlab\Work\'   % location of my LabelListBoxRenderer.class
jRenderer = LabelListBoxRenderer(iconsFolder);
jListbox.setCellRenderer(jRenderer);
 
% Give the icons some space...
jListbox.setFixedCellHeight(18);

This results in the nice-looking listbox whose screenshot appears above. Wasn’t too painful was it?

Using the cell-renderer in Matlab combo-boxes

Customizing Matlab combo-boxes is just as easy, and uses the same LabelListBoxRenderer class:

% Create the Matlab combobox
iconsFolder = fullfile(matlabroot, 'toolbox/matlab/icons');
files = dir(iconsFolder);
hCombobox = uicontrol('Style','popup', 'String',{files.name}, 'Position',[10,10,120,150]);
 
% Find the uicontrol's underlying Java component
jCombobox = findjobj(hCombobox);  % no scroll-pane for combos
 
% Update the combobox's cell-renderer
javaaddpath 'C:\Yair\Undocumented Matlab\Work\'   % location of my LabelListBoxRenderer.class
jRenderer = LabelListBoxRenderer(iconsFolder);
jCombobox.setRenderer(jRenderer);  % Note: not setCellRenderer()
 
% Give the icons some space...
jCombobox.setFixedCellHeight(18);
 
% Make the drop-down list shorter than the default (=20 items)
jCombobox.setMaximumRowCount(8);

For additional aspects of listbox and combobox customizations, refer to sections 6.6 and 6.7 of my Matlab-Java programming book.

 
Related posts:
  1. Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
  2. Customizing listbox & editbox scrollbars Matlab listbox and multi-line editbox uicontrols have pre-configured scrollbars. This article shows how they can be customized....
  3. Customizing menu items part 2 Matlab menu items can be customized in a variety of useful ways using their underlying Java object. ...
  4. Listbox layout customization Matlab's listbox layout can be modified to display multiple item columns and different inter-cell margins. ...
 

Customizing combobox popups

$
0
0

Last week I explained how we can use display custom items in a standard Matlab combobox (popup/dropdown), using its underlying Java component. Today I will show how we can use this Java component for other nice customizations of the combobox’s popup:

Underlying Java component

The first step is to find the underlying Java component of the Matlab combobox (aka popup) uicontrol. This is done using my findjobj utility:

% Create the Matlab combobox
items = {'<HTML><FONT color="red">Hello</Font></html>', 'world', ...
         '<html><font style="font-family:impact;color:green"><i>What a', ...
         '<Html><FONT color="blue" face="Comic Sans MS">nice day!</font>'};
hCombobox = uicontrol('Style','popup', 'Position',[10,100,120,20], 'String',items);
 
% Find the uicontrol's underlying Java component
jCombobox = findjobj(hCombobox);

For findjobj to work, the Matlab uicontrol needs to be visible – it will not have a Java component before it is rendered onscreen for the first time. If everything is successful, jCombobox should now be a reference to the underlying om.mathworks.hg.peer.ComboboxPeer$MLComboBox Java component, which is an extension of the standard Swing JComboBox, as can be seen using my checkClass utility:

>> jCombobox.checkClass
 
private com.mathworks.hg.peer.ComboboxPeer$MLComboBox (uiinspect)
 
Superclass: com.mathworks.mwswing.MJComboBox
Superclass: javax.swing.JComboBox
 
Methods in JComboBox missing in ComboboxPeer$MLComboBox:
   JComboBox()
   JComboBox(java.lang.Object[])
   JComboBox(java.util.Vector)
   JComboBox(javax.swing.ComboBoxModel)
 
Methods in ComboboxPeer$MLComboBox missing in JComboBox:
   ComboboxPeer$MLComboBox(com.mathworks.hg.peer.ComboboxPeer)
   isPopupWidthConstrained() : boolean
   isTipWhenTruncatedEnabled() : boolean
   processEvent(java.awt.AWTEvent)
   registerWithKeyBindingManager(com.mathworks.mwswing.binding.KeyBindingManager, java.lang.String)
   setConstrainPopupWidth(boolean)
   setEditorColumnCount(int)
   setTipWhenTruncatedEnabled(boolean)
 
Methods inherited & modified by ComboboxPeer$MLComboBox:
   getInsets() : java.awt.Insets
   setBackground(java.awt.Color)
   updateUI()
 
Interfaces in JComboBox missing in ComboboxPeer$MLComboBox:
   java.awt.ItemSelectable
   java.awt.event.ActionListener
   javax.accessibility.Accessible
   javax.swing.event.ListDataListener

We shall now use three properties of this object to customize the control’s popup:

MaximumRowCount

The MaximumRowCount numeric property (default=20) sets the maximal number of drop-down items to display in the visible portion of the popup, before requiring a scrollbar. This basically controls the popup’s height:

% Get the current MaximumRowCount value 
numItems = get(jCombobox, 'MaximumRowCount');
numItems = jCombobox.MaximumRowCount;     % equivalent - access the property directly
numItems = jCombobox.getMaximumRowCount;  % equivalent - use Java's accessor method (best way)
 
% Set the MaximumRowCount value
set(jCombobox,'MaximumRowCount',3);
jCombobox.MaximumRowCount = 3;      % equivalent - access the property directly
jCombobox.setMaximumRowCount(3);    % equivalent - use Java's accessor method (best way)

MaximumRowCount=20 (default)

MaximumRowCount=20
(default)

MaximumRowCount=3

MaximumRowCount=3
 

MaximumRowCount=2

MaximumRowCount=2
 

Note that MaximumRowCount is a Matlab extension to the standard Swing JComboBox, so if we use a JComboBox directly in our code (using javacomponent) we will not have this feature. Creating the ComboboxPeer$MLComboBox component instead is possible, but is beyond the scope of this article, because MathWorks chose for this class not to have JComboBox‘s standard constructors but rather only a constructor that accepts a com.mathworks.hg.peer.ComboboxPeer object.

PopupVisible

The PopupVisible property (default=false) is a boolean flag which controls whether the popup window is currently (or should be) displayed. If this property is updated, then the focus is automatically transferred to the popup window for easy item selection using the keyboard (up/down/enter keys). There are also equivalent convenience methods showPopup()/hidePopup():

% Is the popup currently shown?
isShown = get(jCombobox, 'PopupVisible');
isShown = jCombobox.PopupVisible;     % equivalent - access the property directly
isShown = jCombobox.isPopupVisible;   % equivalent - use Java's accessor method (best way)
 
% Display the popup
set(jCombobox,'PopupVisible',true);   % NOT 'on' - this is a Java property, not a Matlab HG one!
jCombobox.PopupVisible = true;        % equivalent - access the property directly
jCombobox.setPopupVisible(true);      % equivalent - use Java's accessor method (best way)
 
% Hide the popup
set(jCombobox,'PopupVisible',false);  % NOT 'off' - this is a Java property, not a Matlab HG one!
jCombobox.PopupVisible = false;       % equivalent - access the property directly
jCombobox.setPopupVisible(false);     % equivalent - use Java's accessor method (best way)

Note that PopUpVisible is not a Matlab extension – it exists in the original Swing JComboBox. Unfortunately, it was not included in the list of properties that are exposed to the user by the high-level Matlab uicontrol, so we need to use the underlying Java component.

On a Windows platform the PopupVisible property is toggled, thereby showing/hiding the popup window, whenever the user clicks <Alt-Up> or <Alt-Down> when the combo-box has focus.

PopupWidthConstrained

The PopupWidthConstrained property (default=false) is a boolean flag which is another Matlab extension to the standard Swing JComboBox. It is apparently used to constrain the width of the drop-down list to the width of the text field. MathWorks took the trouble to add this feature because Swing JComboBox‘s width is constrained, causing a difficulty in distinguishing between popup values when the control is relatively narrow; Matlab’s MJComboBox‘s default unconstrained behavior is much more user-friendly:

PopupWidthConstrained=false (default)

PopupWidthConstrained=false
(default)

PopupWidthConstrained=true

PopupWidthConstrained=true
 

Note that the PopupWidthConstrained property’s read accessor methods is the expected isPopupWidthConstrained(), thereby also enabling the expected Matlab-standard format of get(‘PopupWidthConstrained’). However, the property update accessor method is not the expected setPopupWidthConstrained(flag) but rather a non-standard setConstrainPopupWidth(flag). For this reason, it is impossible to set this property using set(‘PopupWidthConstrained’,…), but only via the Java setConstrainPopupWidth() accessor method:

>> set(jCombobox,'PopupWidthConstrained',true)
??? Changing the 'PopupWidthConstrained' property of javahandle_withcallbacks.com.mathworks.hg.peer.ComboboxPeer$MLComboBox is not allowed.
 
>> jCombobox.setPopupWidthConstrained(true)
??? No appropriate method or public field setPopupWidthConstrained for class javahandle_withcallbacks.com.mathworks.hg.peer.ComboboxPeer$MLComboBox.
 
>> jCombobox.setConstrainPopupWidth(true)  % this is ok

For additional customizations of Matlab comboboxes, refer to section 6.7 of my Matlab-Java programming book.

R2014b

We’re all eagerly awaiting the much-anticipated R2014b release. As you all know, this is an important release with major functionality and engine improvements. It is therefore not surprising that the release date (which should normally have been September 1) is somewhat delayed. MathWorkers are hard at work fixing problems in the pre-release beta. This delay was actually anticipated, as can be seen from the pre-release expiry date.

We should all be patient and let MathWorks fix these issues without pressure. This release could be a real home-run and MathWorks should do all it can to ensure that it works as transparently and as backward-compatible as possible so that it indeed becomes a home run rather than an outfield foul ball. Let’s not have a repeat of R2010b, which required two separate service-pack updates. I urge MathWorks to take their time – better safe than sorry. I urge everyone else to be patient – it’s worth the wait.

When 14b is finally out, I will be here with a planned series of articles explaining how we can make good use of all its new goodies. Start drooling…

Happy Jewish New Year everybody!

 
Related posts:
  1. Customizing listbox/combobox items Matlab listboxes can be customized using custom Java cell-renderers. ...
  2. Customizing listbox & editbox scrollbars Matlab listbox and multi-line editbox uicontrols have pre-configured scrollbars. This article shows how they can be customized....
  3. Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
  4. Customizing menu items part 2 Matlab menu items can be customized in a variety of useful ways using their underlying Java object. ...
 

Customizing axes rulers

$
0
0

Over 4 years have passed since I’ve posted my scoop on Matlab upcoming new graphics system (a.k.a. HG2, Handle Graphics version 2). At that time HG2 was still far from usable, but that has changed when I posted my HG2 update last year. Numerous user feedbacks, by email and blog comments, were reported and the MathWorks developers have listened and improved the code. HG2 was finally released with Matlab R2014b last Friday, and it seems at first glance to be a beauty. I hope my posts and the feedbacks have contributed, but in any case the MathWorks dev group deserves big kudos for releasing a totally new system that provides important usability and aesthetic improvements [almost] without sacrificing performance or backward-compatibility. Trust me, it’s not an easy achievement.

Customized HG2 plot

Customized HG2 plot


One of the nice things that I like about HG2 is that it provides numerous new ways to customize the objects in ways that were impossible (or nearly so) in the old HG1. In R2014b, the leap was large enough that MathWorks wisely chose to limit the official new properties to a bare minimum, for maximal HG1 compatibility. I assume that this will remain also in R2015a, which I expect to be a release devoted to bug fixing and stabilization rather than to new features. I expect the new features to start becoming official in R2015b onward. Such a measured roadmap is to be expected from a responsible engineering company such as MathWorks. So in fact there is no need at all to be disappointed at the relative lack of new functional features. They are all there already, just not yet official, and this is just as it should be.

That being said, if we are aware of the risk that these features might change in the upcoming years until they become official (if ever), then we can start using them today. Experience with this blog has shown that the vast majority of such undocumented features remain working unchanged for years, and some of them eventually become documented. For example, uitab/uitabgroup, on which I posted over 4 years ago and also became official in R2014b after numerous years of running as-is in unofficial form.

In the next few weeks I intend to present a series of posts that highlight some of the undocumented customizations in HG2. I’ll start with some new axes features, followed by plotting aspects.

By the way, “HG2″ is an internal name, that you will find scattered throughout the code but never in the official documentation. Apparently for marketing reasons, MathWorks chose to call it the “New Graphics Engine/System”. I’ll keep using the term HG2, as I think it sounds better than “NGE/NGS”. And besides, old habits die hard…

Axes Rulers

“Rulers” are the X, Y and Z axes lines and all their related aspects, including ticks, tick labels, and secondary label (see below). Some of the important aspects (e.g., ticks and tick labels) have mirror properties in the axes object, for convenience. The ruler objects can be accessed via the hidden properties (XRuler, YRuler and ZRuler, which can be seen using the getundoc utility):

>> x = -10:0.1:10;
>> y = 1e7*sin(x)./x; 
>> hLine = plot(x,y);
>> hAxes = gca;
 
>> yruler = hAxes.YRuler  % or: get(hAxes,'YRuler')
yruler = 
    NumericRuler
 
>> class(yruler)
ans =
matlab.graphics.axis.decorator.NumericRuler
 
>> get(yruler)
                               Axle: [1x1 LineStrip]
                           Children: []
                              Color: [0.15 0.15 0.15]
                           Exponent: 6
                 FirstCrossoverAxis: 0
                FirstCrossoverValue: -Inf
                          FontAngle: 'normal'
                           FontName: 'Helvetica'
                           FontSize: 10
                      FontSmoothing: 'on'
                         FontWeight: 'normal'
                   HandleVisibility: 'off'
                              Label: [1x1 Text]
                          LineWidth: 0.5
                         MajorTicks: [1x1 LineStrip]
                          MinorTick: [1x7 double]
                         MinorTicks: []
                             Parent: [1x1 DecorationContainer]
    PlaceSecondaryLabelAtLowerLimit: 'off'
                              Scale: 'linear'
               SecondCrossoverValue: -Inf
                     SecondaryLabel: [1x1 Text]
                               Tick: [1x8 double]
                            TickDir: 'in'
                          TickLabel: {8x1 cell}
               TickLabelInterpreter: 'tex'
                  TickLabelRotation: 0
                         TickLabels: [1x1 Text]
                         TickLength: 3.255
                            Visible: 'on'

The ruler object itself has plenty of very useful hidden properties (getundoc again…). In R2014b the number of hidden properties for *ALL* objects has multiplied – many standard properties now have hidden internal mirror properties having the “_I” suffix. For example, Tick is a visible property, and Tick_I is hidden. But there are of course other properties that are hidden and are not such internal mirrors. Today I’ll focus on the ruler’s visible properties only.

Axle property

The Axle property controls the axis line, which is a solid black line by default:

>> get(yruler.Axle)
          AlignVertexCenters: 'on'
             AmbientStrength: 0.3
                ColorBinding: 'object'
                   ColorData: [4x1 uint8]
                   ColorType: 'truecolor'
             DiffuseStrength: 0.6
            HandleVisibility: 'off'
                     HitTest: 'off'
                       Layer: 'back'
                   LineStyle: 'solid'
                   LineWidth: 0.5
               NormalBinding: 'none'
                  NormalData: []
                      Parent: [1x1 NumericRuler]
               PickableParts: 'none'
    SpecularColorReflectance: 1
            SpecularExponent: 10
            SpecularStrength: 0.9
                   StripData: [1 3 5]
                     Texture: []
                  VertexData: [3x4 single]
               VertexIndices: []
                     Visible: 'on'
       WideLineRenderingHint: 'software'

As you can see, there are many ways by which we can customize the Axle. For example, let’s use a dotted green line instead of the default solid black line:

hAxes.YRuler.Axle.LineStyle = 'dotted';  % default: 'solid', also possible: dashdot, dashed, none
hAxes.YRuler.Axle.ColorData = uint8([0,100,0,255])';  %=dark green; default: [51 51 51 255], corresponding to [0.2 0.2 0.2 1]

The result can be seen in the screenshot above.

ColorData is closely related to ColorType, which is ‘truecolor’ by default. There are also the alternative ‘colormapped’, ‘texturemapped’, and ‘truecoloralpha’. We can see the various possible combinations if we try to issue an illegal ColorData value:

>> yruler.Axle.ColorData = [.1,.2,.3];
While setting the 'ColorData' property of LineStrip:
Value must be one of the following:
Truecolor  - a 4xN array of type uint8
Colormapped - a 1xN vector of type single
Texturemapped - a 2xN array of type single

For Truecoloralpha, the fourth color value (255 in the example above) signifies the relative transparency: 0=transparent, 255=opaque, and values between 0-255 indicate the degree of translucency.

Note that the default Axle.ColorData sometimes changes between [51 51 51 255] and [38 38 38 255], I’m not sure exactly when this happens. In some cases the YRuler may use ColorData=51 while XRuler uses 38 (which is slightly darker).

We can make interesting effects by specifying non-default VertexData endpoints (array of 3xN singles that should correspond to a 1xN uint32 LineStrip). For example, an axle that spans only part of the axis line… – have fun :-)

Exponent and SecondaryLabel properties

The Exponent controls the computation of the tick label format. For example, in the example above Exponent=6 which means that SecondaryLabel.String=’\times10^{6}’. The exponent is automatically calculated by default, but we can override it to whatever integer we want (non-integer exponent values are rounded to the nearest integer):

hAxes.YRuler.Exponent = -3;

This way we can force the exponent to always have a certain value, or to always display engineering values (multiples of 3). We can do this by attaching a listener to the corresponding axes’ limits, e.g. YLim for the Y-axes.

In addition to forcing the Exponent value, we can also specify a non-numeric SecondaryLabel. For example:

hAxes.YRuler.SecondaryLabel.String = 'millions';  % original: 'x10^{6}'
hAxes.YRuler.SecondaryLabel.FontAngle = 'italic';  % default: 'normal'

The result can be seen in the screenshot above.

Call for action

Go ahead – play around with the new HG2. It’s a lot of fun and quite painless with the new object.property notation. If you have any feedback on the features above or any other, please do share them in a comment below. I’m quite sure that MathWorks will read these comments and this may be a way for you to influence the features that may someday become officially supported. More to the point, make your graphics become even more stunning then they have become with out-of-the-box HG2!

The HG2 customization series will continue next week with a discussion of additional new axes properties, including Baseline, BoxFrame and GridHandle.

Customizing axes part 2

$
0
0

Last week I explained how HG2 (in R2014b) enables us to customize the axes rulers in ways that were previously impossible in HG1 (R2014a or earlier). Today I will describe other useful undocumented customizations of the HG2 axes:

Baseline

A baseline is a line that has some important meaning. For example, in a plot of the sin function, we might want to place a horizontal baseline at Y=0 or Y=-1, and similarly a vertical baseline at X=0. In HG1, we could do this programmatically using extra line commands (presumably with the additional *LimInclude properties). In HG2 it becomes easier – we can simply update the relevant baseline’s properties: XBaseline, YBaseline and ZBaseLine. All baselines are automatically created with a value of 0, color=gray and Visible=’off’. For example, continuing last week’s example:

HG2 axes Baseline

HG2 axes Baseline

% Create the plot
x = -10:0.1:10;
y = 1e7*sin(x)./x; 
hLine = plot(x,y);
hAxes = gca;
 
% Display the default YBaseline's property values
% Note: there are also plenty of hidden properties that can be gotten with getundoc()
>> hAxes.YBaseline.get
           BaseValue: 0
            Children: []
               Color: [0.15 0.15 0.15]
    HandleVisibility: 'off'
           LineStyle: '-'
           LineWidth: 0.5
              Parent: [1x1 DecorationContainer]
             Visible: 'off'
 
% Display a horizontal YBaseline with custom color
hAxes.YBaseline.Color = 'b';  % default: [0.15 0.15 0.15]
hAxes.YBaseline.Visible = 'on';  % default: 'off'
 
% Hide the bottom x-axis, to make the Y-baseline stand out
hAxes.XRuler.Axle.Visible = 'off';  % default: 'on'

Note the horizontal blue Y-baseline. also note how I hid the bottom x-axis, in order to make the Y-baseline stand out.

Translucent colors can be specified by entering a 4-element color vector. For example: [1, 0, 0, 0.5] means a 50%-transparent red.

For extra prominence, you might want to increase the baseline’s LineWidth from its default value of 0.5 to a value of 1 or 2.

Another useful customization is to set a non-zero BaseValue, or a non-solid baseline LineStyle.

While YBaseline is normally a horizontal line that relates to the Y-axis (hAxes.YBaseline.Axis==1), we can make it vertical attached to the X-axis by simply modifying its Axis value to 0 (0=X, 1=Y, 2=Z).

For the record, baselines are matlab.graphics.axis.decorator.Baseline class objects.

BoxFrame

The BoxFrame property controls the “box” lines that surround the plot when we issue a box(‘on’) command. This is normally a simple black square/rectangle for 2D plots, and a simple black background wireframe for a 3D plot. But who said it needs to be boring?

surf(peaks);  % 3D plot
box on;  % standard black box wireframe
boxFrame = get(gca,'BoxFrame');  % or: hAxes.BoxFrame
set(boxFrame, 'XColor','r', 'YColor','b', 'ZColor','g');  % default colors: [0.15 0.15 0.15]
HG2 axes BoxFrame

HG2 axes BoxFrame


The BoxFrame object is a matlab.graphics.axis.decorator.BoxFrame class object that, like the rulers and baseline, can be customized (once the box(‘on’) command has been issued):
>> get(boxFrame)
           AxesLayer: 'bottom'
            BackEdge: [1x1 LineStrip]
            Children: []
           FrontEdge: [1x1 LineStrip]
    HandleVisibility: 'off'
           LineWidth: 0.5
              Parent: [1x1 DecorationContainer]
             Visible: 'off'
              XColor: [0.15 0.15 0.15]
              YColor: [0.15 0.15 0.15]
              ZColor: [0.15 0.15 0.15]

By default, only the box frame’s back-edge is displayed (axes BoxStyle property =’back’). We can modify this behavior by setting the axes’ BoxStyle to ‘full’, but we can have much more control if we simply update the properties of the box-frame object. For example:

set(boxFrame.FrontEdge, 'Visible','on', 'LineStyle','dashdot', 'LineWidth',1);  %defaults: 'off', 'solid', 0.5

As with the Ruler.Axle objects (see last week’s article), we can customize the Vertex points and colors to achieve very colorful effects (anyone say psychedelic?)

GridHandle

In HG2, MathWorks have dramatically improved the appearance of the grid-lines, making them a much lighter, less-obtrusive gray color. Even more importantly, we now have fine-grained control over the grid lines, via the axes’ hidden XGridHandle, YGridHandle and ZGridHandle properties. These return an empty handle when the grid is not shown, and a matlab.graphics.axis.decorator.SimpleGrid class object when the relevant grid-lines are displayed.

>> grid on
>> xgrid = get(gca,'XGridHandle');  % or: hAxes.XGridHandle
>> get(xgrid)
           BackMajorEdge: [1x1 LineStrip]
           BackMinorEdge: [1x1 LineStrip]
                Children: []
                   Color: [0.15 0.15 0.15]
      FirstCrossoverAxis: 0
     FirstCrossoverValue: 0
          FrontMajorEdge: [1x1 LineStrip]
          FrontMinorEdge: [1x1 LineStrip]
           GridLineStyle: '-'
        HandleVisibility: 'off'
               LineWidth: 0.5
              MajorMinor: 'major'
               MajorTick: [-10 -8 -6 -4 -2 0 2 4 6 8 10]
              MinorColor: [0.1 0.1 0.1]
      MinorGridLineStyle: ':'
          MinorLineWidth: 0.5
               MinorTick: []
                  Parent: [1x1 DecorationContainer]
    SecondCrossoverValue: 0
                 Visible: 'on'

As before, we can customize the grid line’s LineWidth, GridLineStyle, and Color. MajorMinor can accept ‘major’ (default), ‘minor’, or ‘majorandminor’, which is pretty intuitive.

customized HG2 axes X-grid

customized HG2 axes X-grid

set(xgrid,'Color','r', 'GridLineStyle',':', 'LineWidth',1.5, 'MajorMinor','majorandminor');

To control the tick lines in 3D plot we can set BackMajorEdge, BackMinorEdge, FrontMajorEdge and FrontMinorEdge in the same way as we did for the BoxFrame. By default only the back-edges are visible. If you wish to also display the front edges, then set the front edge’s Visible to ‘on’ and don’t forget to modify its VertexData to different values than the back edge’s VertexData. As before, colorful effects can be achieved in the grid-lines by customizing the edge objects’ properties:

>> xgrid.BackMajorEdge.get
          AlignVertexCenters: 'on'
             AmbientStrength: 0.3
                ColorBinding: 'object'
                   ColorData: [4x1 uint8]
                   ColorType: 'truecolor'
             DiffuseStrength: 0.6
            HandleVisibility: 'off'
                     HitTest: 'off'
                       Layer: 'back'
                   LineStyle: 'dotted'
                   LineWidth: 1.5
               NormalBinding: 'none'
                  NormalData: []
                      Parent: [1x1 SimpleGrid]
               PickableParts: 'visible'
    SpecularColorReflectance: 1
            SpecularExponent: 10
            SpecularStrength: 0.9
                   StripData: [1 3 5 7 9 11]
                     Texture: []
                  VertexData: [3x10 single]
               VertexIndices: []
                     Visible: 'on'
       WideLineRenderingHint: 'software'

A note about performance

MATLAB HG2, on R2014b, relies on advanced OpenGL hardware features much more than earlier releases. When Matlab detects an incompatible display driver, it issues a warning and reverts to using the much slower software implementation. It is advisable to update the display driver to the very latest version, since this often solves such incompatibilities.

Some computer vendors use custom OEM drivers and their latest version might still be incompatible. For example, on my Lenovo E530 laptop, the latest Intel HG Graphics 4000 driver (v.9.15) was still incompatible; although the system told me that I have the very latest driver installed. I downloaded the latest generic driver (v.10.18) from Intel’s website and this fixed the issue: HG2 now uses hardware-accelerated OpenGL on my laptop, which is much faster. It may not be as 100% compatible with my laptop as the custom OEM version, but so far it appears to work ok and importantly Matlab graphics now work much better. I can always roll-back the driver to the OEM driver if I see a problem with the generic driver.

Next week I will continue my series on Matlab axes customizations, by describing Backdrop, WarpToFill and a few other aspects. Stay tuned!

 
Related posts:
  1. Customizing axes rulers HG2 axes can be customized in numerous useful ways. This article explains how to customize the rulers. ...
  2. Determining axes zoom state The information of whether or not an axes is zoomed or panned can easily be inferred from an internal undocumented object....
  3. Axes LooseInset property Matlab plot axes have an undocumented LooseInset property that sets empty margins around the axes, and can be set to provide a tighter fit of the axes to their surroundings....
  4. Customizing menu items part 1 Matlab menus can be customized in a variety of undocumented manners - first article of a series. ...
 
Viewing all 219 articles
Browse latest View live