Guest bloggers – Undocumented Matlab https://undocumentedmatlab.com Charting Matlab's unsupported hidden underbelly Fri, 15 Dec 2017 10:51:42 +0000 en-US hourly 1 https://wordpress.org/?v=4.4.1 Matlab compilation quirks – take 2https://undocumentedmatlab.com/blog/matlab-compilation-quirks-take-2 https://undocumentedmatlab.com/blog/matlab-compilation-quirks-take-2#respond Wed, 31 May 2017 18:00:42 +0000 http://undocumentedmatlab.com/?p=6919
 
Related posts:
  1. Matlab compiler bug and workaround Both the Matlab compiler and the publish function have errors when parsing block-comments in Matlab m-code. ...
  2. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
  3. 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. ...
  4. Handle Graphics Behavior HG behaviors are an important aspect of Matlab graphics that enable custom control of handle functionality. ...
 
]]>
Once again I would like to welcome guest blogger Hanan Kavitz of Applied Materials. Hanan posted a couple of guest posts here over the past few years, including a post last year about quirks with Matlab-compiled DLLs. Today Hanan will follow up on that post by discussing several additional quirks that they have encountered with Matlab compilations/deployment.

Don’t fix it, if it ain’t broke…

In Applied Materials Israel (PDC) we use Matlab code for both algorithm development and deployment (production). As part of the dev-ops build system, which builds our product software versions, we build Matlab artifacts (binaries) from the Matlab source code.

A typical software version has several hundreds Matlab artifacts that are automatically rebuilt on a daily basis, and we have many such versions – totaling many thousands of compilations each day.

This process takes a long time, so we were looking for a way to make it more efficient.

The idea that we chose to implement sounds simple – take a single binary module in any software version (Ex. foo.exe – Matlab-compiled exe) and check it: if the source code for this module has not changed since the last compilation then simply don’t compile it, just copy it from previous software version repository. Since most of our code doesn’t change daily (some of it hasn’t changed in years), we can skip the compilation time of most binaries and just copy them from some repository of previously compiled binaries.

In a broader look, avoiding lengthy compilations cycles by not compiling unchanged code is a common programming practice, implemented by all modern compilers. For example, the ‘make’ utility uses a ‘makefile’ to check the time stamps of all dependencies of every object file in order to decide which object requires recompilation. In reality, this is not always the best solution as time stamps may be incorrect, but it works well in the vast majority of cases.

Coming back to Matlab, now comes the hard part – how could our build system know that nothing has changed in module X and that something has changed in module Y? How does it even know which source files it needs to ensure didn’t change?

The credit for the idea goes to my manager, Lior Cohen, as follows: You can actually check the dependency of a given binary after compilation. The basis of the solution is that a Matlab executable is in fact a compressed (zip) file. The idea is then to:

  1. Compile the binary once
  2. Unzip the binary and “see” all your dependencies (source files are encrypted and resources are not, but we only need the list of file names – not their content).
  3. Now build a list of all your dependency files and compute the CRC value of each from the source control. Save it for the next time you are required to compile this module.
  4. In the next compilation cycle, find this dependency list, review it, dependency source file at a time and make sure CRC of the dependency hasn’t changed since last time.
  5. If no dependency CRC has changed, then copy the binary from the repository of previous software version, without compiling.
  6. Otherwise, recompile the binary and rebuild the CRC list of all dependencies again, in preparation for the next compilation cycle.

That’s it! That simple? Well… not really – the reality is a bit more complex since there are many other dependencies that need to be checked. Some of them are:

  1. Did the requested Matlab version of the binary change since the last compilation?
  2. Did the compilation instructions themselves (we have a sort of ‘makefile’) change?

Basically, I implemented a policy that if anything changed, or if the dependency check itself failed, then we don’t take any chances and just compile this binary. Keeping in mind that this dependencies check and file copying is much faster than a Matlab compilation, we save a lot of actual compilation time using this method.

Bottom line: Given a software version containing hundreds of compilation instructions to execute and assuming not much has changed in the version (which is often the case), we skip over 90% of compilations altogether and only rebuild what really changed. The result is a version build that takes about half an hour, instead of many hours. Moreover, since the compilation process is working significantly less, we get fewer failures, fewer stuck or crashed mcc processes, and [not less importantly] less maintenance required by me.

Note that in our implementation we rely on the undocumented fact that Matlab binaries are in fact compressed zip archives. If and when a future Matlab release will change the implementation such that the binaries will no longer be zip archives, another way will need to be devised in order to ensure the consistency of the target executable with its dependent source files.

Don’t kill it, if it ain’t bad…

I want to share a very weird issue I investigated over a year ago when using Matlab compiled exe. It started with a user showed me a Matlab compiled exe that didn’t run – I’m not talking about a regular Matlab exception: the process was crashing with an MS Windows popup window popping, stating something very obscure.

It was a very weird behavior that I couldn’t explain – the compiler seemed to work well but the compiled executable process kept crashing. Compiling completely different code showed the same behavior.

This issue has to do with the system compiler configuration that is being used. As you might know, when installing the Matlab compiler, before the first compilation is ever made, the user has to state the C compiler that the Matlab compiler should use in its compilation process. This is done by command ‘mbuild –setup’. This command asks the users to choose the C compiler and saves the configuration (batch file back then, xml in the newer versions of Matlab) in the user’s prefdir folder. At the time we were using Microsoft Visual C++ compiler 9.0 SP1.

The breakthrough in the investigation came when I ran mcc command with –verbose flag, which outputs much more compilation info than I would typically ever want… I discovered that although the target executable file had been created, a post compilation step failed to execute, while issuing a very cryptic error message:

mt.exe : general error c101008d: Failed to write the updated manifest to the resource of file “…”. Access is denied.

cryptic compilation error (click to zoom)

cryptic compilation error (click to zoom)

The failure was in one of the ‘post link’ commands in the configuration batch file – something obscure such as this:

set POSTLINK_CMDS2=mt.exe -outputresource: %MBUILD_OUTPUT_FILE_NAME%;%MANIFEST_RESOURCE% -manifest "%MANIFEST_FILE_NAME%"

This line of code takes an XML manifest file and inserts it into the generated binary file (additional details).

If you open a valid R2010a (and probably other old versions as well) Matlab-generated exe in a text editor you can actually see a small XML code embedded in it, while in a non-functioning exe I could not see this XML code.

So why would this command fail?

It turned out, as funny as it sounds, to be an antivirus issue – our IT department updated its antivirus policies and this ‘post link’ command suddenly became an illegal operation. Once our IT eased the policy, this command worked well again and the compiled executables stopped crashing, to our great joy.

]]>
https://undocumentedmatlab.com/blog/matlab-compilation-quirks-take-2/feed 0
Quirks with parfor vs. forhttps://undocumentedmatlab.com/blog/quirks-with-parfor-vs-for https://undocumentedmatlab.com/blog/quirks-with-parfor-vs-for#comments Thu, 05 Jan 2017 17:15:48 +0000 http://undocumentedmatlab.com/?p=6821
 
Related posts:
  1. Matlab mex in-place editing Editing Matlab arrays in-place can be an important technique for optimizing calculations. This article shows how to do it using Mex. ...
  2. Preallocation performance Preallocation is a standard Matlab speedup technique. Still, it has several undocumented aspects. ...
  3. Array resizing performance Several alternatives are explored for dynamic array growth performance in Matlab loops. ...
  4. Matlab’s internal memory representation Matlab's internal memory structure is explored and discussed. ...
 
]]>
A few months ago, I discussed several tips regarding Matlab’s parfor command, which is used by the Parallel Computing Toolbox (PCT) for parallelizing loops. Today I wish to extend that post with some unexplained oddities when using parfor, compared to a standard for loop.

Data serialization quirks

Dimitri Shvorob may not appear at first glance to be a prolific contributor on Matlab Central, but from the little he has posted over the years I regard him to be a Matlab power-user. So when Dimitri reports something, I take it seriously. Such was the case several months ago, when he contacted me regarding very odd behavior that he saw in his code: the for loop worked well, but the parfor version returned different (incorrect) results. Eventually, Dimitry traced the problem to something originally reported by Dan Austin on his Fluffy Nuke It blog.

The core issue is that if we have a class object that is used within a for loop, Matlab can access the object directly in memory. But with a parfor loop, the object needs to be serialized in order to be sent over to the parallel workers, and deserialized within each worker. If this serialization/deserialization process involves internal class methods, the workers might see a different version of the class object than the one seen in the serial for loop. This could happen, for example, if the serialization/deserialization method croaks on an error, or depends on some dynamic (or random) conditions to create data.

In other words, when we use data objects in a parfor loop, the data object is not necessarily sent “as-is”: additional processing may be involved under the hood that modify the data in a way that may be invisible to the user (or the loop code), resulting in different processing results of the parallel (parfor) vs. serial (for) loops.

For additional aspects of Matlab serialization/deserialization, see my article from 2 years ago (and its interesting feedback comments).

Data precision quirks

The following section was contributed by guest blogger Lior Perlmuter-Shoshany, head algorithmician at a private equity fund.

In my work, I had to work with matrixes in the order of 109 cells. To reduce the memory footprint (and hopefully also improve performance), I decided to work with data of type single instead of Matlab’s default double. Furthermore, in order to speed up the calculation I use parfor rather than for in the main calculation. In the end of the run I am running a mini for-loop to see the best results.

What I discovered to my surprise is that the results from the parfor and for loop variants is not the same!

The following simplified code snippet illustrate the problem by calculating a simple standard-deviation (std) over the same data, in both single– and double-precision. Note that the loops are ran with only a single iteration, to illustrate the fact that the problem is with the parallelization mechanism (probably the serialization/deserialization parts once again), not with the distribution of iterations among the workers.

clear
rng('shuffle','twister');
 
% Prepare the data in both double and single precision
arr_double = rand(1,100000000);
arr_single = single(arr_double);
 
% No loop - direct computation
std_single0 = std(arr_single);
std_double0 = std(arr_double);
 
% Loop #1 - serial for loop
std_single = 0;
std_double = 0;
for i=1
    std_single(i) = std(arr_single);
    std_double(i) = std(arr_double);
end
 
% Loop #2 - parallel parfor loop
par_std_single = 0;
par_std_double = 0;
parfor i=1
    par_std_single(i) = std(arr_single);
    par_std_double(i) = std(arr_double);
end
 
% Compare results of for loop vs. non-looped computation
isForSingleOk = isequal(std_single, std_single0)
isForDoubleOk = isequal(std_double, std_double0)
 
% Compare results of single-precision data (for vs. parfor)
isParforSingleOk = isequal(std_single, par_std_single)
parforSingleAccuracy = std_single / par_std_single
 
% Compare results of double-precision data (for vs. parfor)
isParforDoubleOk = isequal(std_double, par_std_double)
parforDoubleAccuracy = std_double / par_std_double

Output example :

isForSingleOk = 
    1                   % <= true (of course!)
isForDoubleOk =
    1                   % <= true (of course!)
 
isParforSingleOk =
    0                   % <= false (odd!)
parforSingleAccuracy =
    0.73895227413361    % <= single-precision results are radically different in parfor vs. for
 
isParforDoubleOk =
    0                   % <= false (odd!)
parforDoubleAccuracy =
    1.00000000000021    % <= double-precision results are almost [but not exactly] the same in parfor vs. for

From my testing, the larger the data array, the bigger the difference is between the results of single-precision data when running in for vs. parfor.

In other words, my experience has been that if you have a huge data matrix, it’s better to parallelize it in double-precision if you wish to get [nearly] accurate results. But even so, I find it deeply disconcerting that the results are not exactly identical (at least on R2015a-R2016b on which I tested) even for the native double-precision .

Hmmm… bug?

Upcoming travels – Zürich & Geneva

I will shortly be traveling to clients in Zürich and Geneva, Switzerland. If you are in the area and wish to meet me to discuss how I could bring value to your work with some advanced Matlab consulting or training, then please email me (altmany at gmail):

  • Zürich: January 15-17
  • Geneva: January 18-21

Happy new year everybody!

]]>
https://undocumentedmatlab.com/blog/quirks-with-parfor-vs-for/feed 7
Checking status of warning messages in MEXhttps://undocumentedmatlab.com/blog/checking-status-of-warning-messages-in-mex https://undocumentedmatlab.com/blog/checking-status-of-warning-messages-in-mex#respond Wed, 21 Dec 2016 15:24:06 +0000 http://undocumentedmatlab.com/?p=6797
 
Related posts:
  1. Inactive Control Tooltips & Event Chaining Inactive Matlab uicontrols cannot normally display their tooltips. This article shows how to do this with a combination of undocumented Matlab and Java hacks....
  2. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  3. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  4. Undocumented Matlab MEX API Matlab's MEX API contains numerous undocumented functions, that can be extremely useful. ...
 
]]>
Once again I would like to welcome guest blogger Pavel Holoborodko, the developer of the Advanpix Multiprecision Computing Toolbox. Pavel has already posted here as a guest blogger about undocumented Matlab MEX functions. Today he will discuss another little-known aspect of advanced MEX programming with Matlab, a repost of an article that was originally posted on his own blog. Happy holidays everybody!

Matlab allows flexible adjustment of visibility of warning messages. Some, or even all, messages can be disabled from showing on the screen by warning command.

The little known fact is that status of some warnings may be used to change the execution path in algorithms. For example, if warning 'Matlab:nearlySingularMatrix' is disabled, then the linear system solver (mldivide operator) might skip estimation of reciprocal condition number which is used exactly for the purpose of detection of nearly singular matrices. If the trick is used, it allows 20%-50% boost in solver performance, since rcond estimation is a time consuming process.

Therefore it is important to be able to retrieve status of warnings in Matlab. Especially in MEX libraries targeted for improved performance. Unfortunately Matlab provides no simple way to check status of warning message from MEX module.

Today’s article outlines two workarounds for the issue:

  1. Using mexCallMATLABWithTrap (documented)
  2. Using utGetWarningStatus (undocumented)

Using mexCallMATLABWithTrap (documented)

The first idea is to use documented mexCallMATLABWithTrap function to execute warning(‘query’,…) command using Matlab’s interpreter and then parse the returned result:

bool mxIsWarningEnabled(const char* warningId)
{
    bool enabled = true;
 
    if (NULL != warningId)
    {
        mxArray *mxCommandResponse = NULL, *mxException = NULL;
        mxArray *args[2];
 
        /* warning('query', warningId); */
        args[0] = mxCreateString("query");
        args[1] = mxCreateString(warningId);
        mxException = mexCallMATLABWithTrap(1,&mxCommandResponse,2,args,"warning");
        if (NULL == mxException && NULL != mxCommandResponse)
        {
            if (mxIsStruct(mxCommandResponse))
            {
                const mxArray* state_field = mxGetField(mxCommandResponse, 0, "state");
                if (mxIsChar(state_field))
                {
                    char state_value[8] = {0};
                    enabled = (0 == mxGetString(state_field, state_value, 8)) &&
                              (0 == strcmp(state_value,"on"));
                }
            }
            mxDestroyArray(mxCommandResponse);
        }
        else
        {
            /* 'warning' returned with error */
            mxDestroyArray(mxException);
        }
        mxDestroyArray(args[0]);
        mxDestroyArray(args[1]);
    }
    return enabled;
}

This approach is slow, but works fine in most standard situations. See the bottom of this post for a usage example.

However, this approach has an important drawback – we should be careful with recursive calls to the Matlab interpreter (Matlab -> MEX -> Matlab) and with handling Matlab errors in MEX. It is safe only if we use identical standard libraries and compiler to build both MEX and Matlab.

In other cases, for example when MEX is targeted to work with different versions of Matlab, or was built with a different standard library and compiler, etc. – cross boundary handling of errors (which are just C++ exceptions) might lead to unpredictable results, most likely segfaults.

Using utGetWarningStatus (undocumented)

To avoid all the overhead of calling Matlab interpreter and unsafe error handling, we can use some undocumented internal Matlab functions:

/* Link with libut library to pick-up undocumented functions: */
extern "C" void* utGetWarningManagerContext(void);
extern "C" bool  utIsValidMessageIdentifier(const char *warningId);
extern "C" bool  utGetWarningStatus(void* context, const char *warningId);
 
/* 
   Returns true if warning with warningId enabled 
   Matlab versions supported/tested: R2008b - R2016b
*/
bool mxIsWarningEnabled(const char *warningId)
{
    bool enabled = true;
 
    if (NULL != warningId && utIsValidMessageIdentifier(warningId))
    {
        void* context = utGetWarningManagerContext();
        enabled = (NULL != context) && utGetWarningStatus(context, warningId);
    }
    return enabled;
}

Now the code is clean, fast and safe – we bypass the interpreter and work directly with Matlab kernel. All the undocumented functions involved are present in Matlab for at least 10 years and do simple logical checks under the hood.

The standard function mexWarnMsgIdAndTxt uses similar code to check if it should display the warning or just suppress it, and that code remains unchanged since R2008b. This is a good indication of code stability and makes us believe that it will not be changed in future versions of Matlab.

For both workarounds, usage is simple:

if (mxIsWarningEnabled("Matlab:nearlySingularMatrix"))
{
   /* compute rcond */
}
else
{
   /* do something else */
}
]]>
https://undocumentedmatlab.com/blog/checking-status-of-warning-messages-in-mex/feed 0
Customizing uifigures part 2https://undocumentedmatlab.com/blog/customizing-uifigures-part-2 https://undocumentedmatlab.com/blog/customizing-uifigures-part-2#comments Wed, 07 Sep 2016 17:00:57 +0000 http://undocumentedmatlab.com/?p=6635
 
Related posts:
  1. uiundo – Matlab’s undocumented undo/redo manager The built-in uiundo function provides easy yet undocumented access to Matlab's powerful undo/redo functionality. This article explains its usage....
  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. Uitable sorting Matlab's uitables can be sortable using simple undocumented features...
  4. Frameless (undecorated) figure windows Matlab figure windows can be made undecorated (borderless, title-less). ...
 
]]>
I would like to introduce guest blogger Iliya Romm of Israel’s Technion Turbomachinery and Heat Transfer Laboratory. Today Iliya will discuss how Matlab’s new web-based figures can be customized with user-controlled CSS and JavaScript code.

When we compare the documented properties of a “classic” uicontrol with an App Designer control such as uicheckbox, we see lists of 42 and 15 properties, respectively. At first glance, this implies that our ability to customize App Designer elements is relatively very limited. This is surely a disquieting conclusion, especially for those used to being able to change most aspect of their Matlab figures via Java. Fortunately, such a conclusion is quite far from reality, as we will shortly see.

To understand this claim, we need to consider a previous post on this blog, where Yair discussed how uifigures are actually HTML webpages rendered by Matlab. As such, they have a DOM that can be accessed and manipulated through JavaScript commands to achieve various visual customizations. Today we’ll explore the structure of the uifigure webpage; take a look at some possibilities provided by the Dojo Toolkit; and see how to use Dojo to customize uifigure controls visually using CSS styles and/or HTML attributes.

User customizations of Matlab uifigures (click to zoom-in)
User customizations of Matlab uifigures (click to zoom-in)

A brief introduction to CSS

CSS stands for Cascading Style Sheets. As described on the official webpage of W3C (which governs web standards):

CSS is the language for describing the presentation of Web pages, including colors, layout, and fonts. CSS is independent of HTML. This is referred to as the separation of structure (or: content) from presentation.

CSS rules (or “styles”) can be defined in one of three places:

  • A separate file, such as the main.css that Matlab uses for uifigures (this file is found minified in %matlabroot%\toolbox\matlab\uitools\uifigureappjs\release\gbtclient\css)
  • An inline block inside the HTML’s <head> section
  • Directly within a DOM node

Deciding which of the above to use, is largely a choice of the right tool for the job. Usually, the first two choices should be preferred, as they adhere to the “separation of structure and presentation” idea better. However, in the scope of this demonstration, we’ll be using mostly the 3rd option, because it allows us not to worry about possible CSS precedence issues (suggested read).

The syntax of CSS is generally: selector { property: value }, but it can have other forms as well.

Getting down to business

Let us consider a very basic uifigure that only contains a uitextarea and its label:

Simple demo uifigure with a TextArea and label

Simple demo uifigure with a TextArea and label

The auto-generated code for it is:

classdef DOMdemo < matlab.apps.AppBase
 
    % Properties that correspond to app components
    properties (Access = public)
        UIFigure      matlab.ui.Figure           % UI Figure
        LabelTextArea matlab.ui.control.Label    % Text Area
        TextArea      matlab.ui.control.TextArea % This is some text.        
    end
 
    methods (Access = private)
        % Code that executes after component creation
        function startupFcn(app)
        end
    end
 
    % App initialization and construction
    methods (Access = private)
 
        % Create UIFigure and components
        function createComponents(app)
            % Create UIFigure
            app.UIFigure = uifigure;
            app.UIFigure.Position = [100 100 280 102];
            app.UIFigure.Name = 'UI Figure';
            setAutoResize(app, app.UIFigure, true)
 
            % Create LabelTextArea
            app.LabelTextArea = uilabel(app.UIFigure);
            app.LabelTextArea.HorizontalAlignment = 'right';
            app.LabelTextArea.Position = [16 73 62 15];
            app.LabelTextArea.Text = 'Text Area';
 
            % Create TextArea
            app.TextArea = uitextarea(app.UIFigure);
            app.TextArea.Position = [116 14 151 60];
            app.TextArea.Value = {'This is some text.'};
        end
    end
 
    methods (Access = public)
 
        % Construct app
        function app = DOMdemo()
            % Create and configure components
            createComponents(app)
 
            % Register the app with App Designer
            registerApp(app, app.UIFigure)
 
            % Execute the startup function
            runStartupFcn(app, @startupFcn)
 
            if nargout == 0
                clear app
            end
        end
 
        % Code that executes before app deletion
        function delete(app)
            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end

Let’s say we want to modify certain aspects of the TextArea widget, such as the text color, background, and/or horizontal alignment. The workflow for styling elements involves:

  1. Find the handle to the webfigure
  2. Find the DOM node we want to modify
  3. Find the property name that corresponds to the change we want
  4. Find a way to manipulate the desired node from Matlab

Step 1: Find the handle to the webfigure

The first thing we need to do is to strategically place a bit of code that would allow us to get the URL of the figure so we can inspect it in our browser:

function startupFcn(app)
   % Customizations (aka "MAGIC GOES HERE"):
   warning off Matlab:HandleGraphics:ObsoletedProperty:JavaFrame
   warning off Matlab:structOnObject    
   while true
      try   
         win = struct(struct(struct(app).UIFigure).Controller).Container.CEF;
         disp(win.URL);
         break
      catch
         disp('Not ready yet!');
         pause(0.5); % Give the figure (webpage) some more time to load
      end
   end
end

This code waits until the page is sufficiently loaded, and then retrieve its local address (URL). The result will be something like this, which can be directly opened in any browser (outside Matlab):

http://localhost:31415/toolbox/matlab/uitools/uifigureappjs/componentContainer.html?channel=/uicontainer/861ef484-534e-4a50-993e-6d00bdba73a5&snc=88E96E

Step 2: Find the DOM node that corresponds to the component that we want to modify

Loading this URL in an external browser (e.g., Chrome, Firefox or IE/Edge) enables us to use web-development addins (e.g., FireBug) to inspect the page contents (source-code). Opening the URL inside a browser and inspecting the page contents, we can see its DOM:

Inspecting the DOM in Firefox (click to zoom-in)
Inspecting the DOM in Firefox (click to zoom-in)

Notice the three data-tag entries marked by red frames. Any idea why there are exactly three nonempty tags like that? This is because our App Designer object, app, contains 3 declared children, as defined in:

createComponents(app):
    app.UIFigure = uifigure;
    app.LabelTextArea = uilabel(app.UIFigure);
    app.TextArea = uitextarea(app.UIFigure);

… and each of them is assigned a random hexadecimal id whenever the app is opened.

Finding the relevant node involved some trial-and-error, but after doing it several times I seem to have found a consistent pattern that can be used to our advantage. Apparently, the nodes with data-tag are always above the element we want to style, sometimes as a direct parent and sometimes farther away. So why do we even need to bother with choosing more accurate nodes than these “tagged” ones? Shouldn’t styles applied to the tagged nodes cascade down to the element we care about? Sure, sometimes it works like that, but we want to do better than “sometimes”. To that end, we would like to select as relevant a node as possible.

Anyway, the next step in the program is to find the data-tag that corresponds to the selected component. Luckily, there is a direct (undocumented) way to get it:

% Determine the data-tag of the DOM component that we want to modify:
hComponent = app.TextArea;  % handle to the component that we want to modify
data_tag = char(struct(hComponent).Controller.ProxyView.PeerNode.getId);  % this part is generic: can be used with any web-based GUI component

Let’s take a look at the elements marked with blue and green borders (in that order) in the DOM screenshot. We see that the data-tag property is exactly one level above these elements, in other words, the first child of the tagged node is an element that contains a widgetid property. This property is very important, as it contains the id of the node that we actually want to change. Think pointers. To summarize this part:

data-tag   =>   widgetid   =>   widget “handle”

We shall use this transformation in Step 4 below.

I wanted to start with the blue-outlined element as it demonstrates this structure using distinct elements. The green-outlined element is slightly strange, as it contains a widgetid that points back to itself. Since this obeys the same algorithm, it’s not a problem.

Step 3: Find the CSS property name that corresponds to the change we want

There is no trick here: it’s just a matter of going through a list of CSS properties and choosing one that “sounds about right” (there are often several ways to achieve the same visual result with CSS). After we choose the relevant properties, we need to convert them to camelCase as per documentation of dojo.style():

If the CSS style property is hyphenated, the JavaScript property is camelCased. For example: “font-size” becomes “fontSize”, and so on.

Note that Matlab R2016a comes bundled with Dojo v1.10.4, rev. f4fef70 (January 11 2015). Other Matlab releases will probably come with other Dojo versions. They will never be the latest version of Dojo, but rather a version that is 1-2 years old. We should keep this in mind when searching the Dojo documentation. We can get the current Dojo version as follows:

>> f=uifigure; drawnow; dojoVersion = matlab.internal.webwindowmanager.instance.windowList(1).executeJS('dojo.version'), delete(f)
dojoVersion =
{"major":1,"minor":10,"patch":4,"flag":"","revision":"f4fef70"}

This tells us that Dojo 1.10.4.f4fef70 is the currently-used version. We can use this information to browse the relevant documentation branch, as well as possibly use different Dojo functions/features.

Step 4: Manipulate the desired element from Matlab

In this demo, we’ll use a combination of several commands:

  • {matlab.internal.webwindow.}executeJS() – For sending JS commands to the uifigure.
  • dojo.query() – for finding nodes inside the DOM.
  • dojo.style() (deprecated since v1.8) – for applying styles to the required nodes of the DOM.
    Syntax: dojo.style(node, style, value);
  • dojo.setAttr (deprecated since v1.8) – for setting some non-style attributes.
    Syntax: dojo.setAttr(node, name, value);

Consider the following JS commands:

  • search the DOM for nodes having a data-tag attribute having the specified value, take their first child of type <div>, and return the value of this child’s widgetid attribute:
    ['dojo.getAttr(dojo.query("[data-tag^=''' data_tag '''] > div")[0],"widgetid")']
  • search the DOM for nodes with id of widgetid, then take the first element of the result and set its text alignment:
    ['dojo.style(dojo.query("#' widgetId(2:end-1) '")[0],"textAlign","center")']
  • append the CSS style defined by {SOME CSS STYLE} to the page (this style can later be used by nodes):
    ['document.head.innerHTML += ''<style>{SOME CSS STYLE}</style>''']);

Putting it all together

It should finally be possible to understand the code that appears in the animated screenshot at the top of this post:

%% 1. Get a handle to the webwindow:
win = struct(struct(struct(app).UIFigure).Controller).Container.CEF;
 
%% 2. Find which element of the DOM we want to edit (as before):
data_tag = char(struct(app.TextArea).Controller.ProxyView.PeerNode.getId);
 
%% 3. Manipulate the DOM via a JS command
% ^ always references a class="vc-widget" element.
widgetId = win.executeJS(['dojo.getAttr(dojo.query("[data-tag^=''' data_tag '''] > div")[0],"widgetid")']);
 
% Change font weight:
dojo_style_prefix = ['dojo.style(dojo.query("#' widgetId(2:end-1) '")[0],'];
win.executeJS([dojo_style_prefix '"fontWeight","900")']);
 
% Change font color:
win.executeJS([dojo_style_prefix '"color","yellow")']);
 
% Add an inline css to the HTML <head>:
win.executeJS(['document.head.innerHTML += ''<style>'...
    '@-webkit-keyframes mymove {50% {background-color: blue;}}'...
    '@keyframes mymove {50% {background-color: blue;}}</style>''']);
 
% Add animation to control:      
win.executeJS([dojo_style_prefix '"-webkit-animation","mymove 5s infinite")']);
 
% Change Dojo theme:
win.executeJS('dojo.setAttr(document.body,''class'',''nihilo'')[0]');
 
% Center text:
win.executeJS([dojo_style_prefix '"textAlign","center")']);

A similar method for center-aligning the items in a uilistbox is described here (using a CSS text-align directive).

The only thing we need to ensure before running code that manipulates the DOM, is that the page is fully loaded. The easiest way is to include a pause() of several seconds right after the createComponents(app) function (this will not interfere with the creation of the uifigure, as it happens on a different thread). I have been experimenting with another method involving webwindow‘s PageLoadFinishedCallback callback, but haven’t found anything elegant yet.

A few words of caution

In this demonstration, we invoked Dojo functions via the webwindow’s JS interface. For something like this to be possible, there has to exist some form of “bridge” that translates Matlab commands to JS commands issued to the browser and control the DOM. We also know that this bridge has to be bi-directional, because binding Matlab callbacks to uifigure actions (e.g. ButtonPushFcn for uibuttons) is a documented feature.

The extent to which the bridge might allow malicious code to control the Matlab process needs to be investigated. Until then, the ability of webwindows to execute arbitrary JS code should be considered a known vulnerability. For more information, see XSS and related vulnerabilities.

Final remarks

It should be clear now that there are actually lots of possibilities afforded by the new uifigures for user customizations. One would hope that future Matlab releases will expose easier and more robust hooks for CSS/JS customizations of uifigure contents. But until that time arrives (if ever), we can make do with the mechanism shown above.

Readers are welcome to visit the GitHub project dedicated to manipulating uifigures using the methods discussed in this post. Feel free to comment, suggest improvements and ideas, and of course submit some pull requests :)

p.s. – it turns out that uifigures can also display MathML. But this is a topic for another post…

]]>
https://undocumentedmatlab.com/blog/customizing-uifigures-part-2/feed 2
Zero-testing performancehttps://undocumentedmatlab.com/blog/zero-testing-performance https://undocumentedmatlab.com/blog/zero-testing-performance#comments Wed, 31 Aug 2016 17:00:44 +0000 http://undocumentedmatlab.com/?p=6622
 
Related posts:
  1. uicontextmenu performance Matlab uicontextmenus are not automatically deleted with their associated objects, leading to leaks and slow-downs. ...
  2. rmfield performance The performance of the builtin rmfield function (as with many other builtin functions) can be improved by simple profiling. ...
  3. tic / toc – undocumented option Matlab's built-in tic/toc functions have an undocumented option enabling multiple nested clockings...
  4. Solving a MATLAB bug by subclassing Matlab's Image Processing Toolbox's impoint function contains an annoying bug that can be fixed using some undocumented properties....
 
]]>
I would like to introduce guest blogger Ken Johnson, a MATLAB Connections partner specializing in electromagnetic optics simulation. Today Ken will explore some performance subtleties of zero testing in Matlab.

I often have a need to efficiently test a large Matlab array for any nonzero elements, e.g.

>> a = zeros(1e4);
>> tic, b = any(a(:)~=0); toc
Elapsed time is 0.126118 seconds.

Simple enough. In this case, when a is all-zero, the internal search algorithm has no choice but to inspect every element of the array to determine whether it contains any nonzeros. In the more typical case where a contains many nonzeros you would expect the search to terminate almost immediately, as soon as it finds the first nonzero. But that’s not how it works:

>> a = round(rand(1e4));
>> tic, b = any(a(:)~=0); toc
Elapsed time is 0.063404 seconds.

There is significant runtime overhead in constructing the logical array “a(:)~=0”, although the “any(…)” operation apparently terminates at the first true value it finds.

The overhead can be eliminated by taking advantage of the fact that numeric values may be used as logicals in Matlab, with zero implicitly representing false and nonzero representing true. Repeating the above test without “~=0”, we get a huge runtime improvement:

>> a = round(rand(1e4));
>> tic, b = any(a(:)); toc
Elapsed time is 0.000026 seconds.

However, there is no runtime benefit when a is all-zero:

>> a = zeros(1e4);
>> tic, b = any(a(:)); toc
Elapsed time is 0.125120 seconds.

(I do not quite understand this. There should be some runtime benefit from bypassing the logical array construction.)

NaN values

There is also another catch: The above efficiency trick does not work when a contains NaN values (if you consider NaN to be nonzero), e.g.

>> any([0,nan])
ans =
     0

The any function ignores entries that are NaN, meaning it treats NaNs as zero-equivalent. This is inconsistent with the behavior of the inequality operator:

>> any([0,nan]~=0)
ans =
     1

To avoid this problem, an explicit isnan test is needed. Efficiency is not impaired when a contains many nonzeros, but there is a 2x efficiency loss when a is all-zero:

>> a = round(rand(1e4));
>> tic, b = any(a(:)) || any(isnan(a(:))); toc
Elapsed time is 0.000027 seconds.
 
>> a = zeros(1e4);
>> tic, b = any(a(:)) || any(isnan(a(:))); toc
Elapsed time is 0.256604 seconds.

For testing all-nonzero the NaN problem does not occur:

>> all([1 nan])
ans =
     1

In this context NaN is treated as nonzero and the all-nonzero test is straightforward:

>> a = round(rand(1e4));
>> tic, b = all(a(:)); toc
Elapsed time is 0.000029 seconds.

For testing any-zero and all-zero, use the complements of the above tests:

>> b = ~any(a(:)) || any(isnan(a(:)));  % all zero?
>> b = ~all(a(:));  % any zero?

Efficient find

The find operation can also be optimized by bypassing construction of a logical temporary array, e.g.

>> a = round(rand(1e4));
>> tic, b = find(a(:)~=0, 1); toc
Elapsed time is 0.065697 seconds.
 
>> tic, b = find(a(:), 1); toc
Elapsed time is 0.000029 seconds.

There is no problem with NaNs in this case; the find function treats NaN as nonzero, e.g.

>> find([0,nan,1], 1)
ans =
     2
]]>
https://undocumentedmatlab.com/blog/zero-testing-performance/feed 5
rmfield performancehttps://undocumentedmatlab.com/blog/rmfield-performance https://undocumentedmatlab.com/blog/rmfield-performance#comments Wed, 25 May 2016 07:00:48 +0000 http://undocumentedmatlab.com/?p=6427
 
Related posts:
  1. tic / toc – undocumented option Matlab's built-in tic/toc functions have an undocumented option enabling multiple nested clockings...
  2. Solving a MATLAB bug by subclassing Matlab's Image Processing Toolbox's impoint function contains an annoying bug that can be fixed using some undocumented properties....
  3. Plot LimInclude properties The plot objects' XLimInclude, YLimInclude, ZLimInclude, ALimInclude and CLimInclude properties are an important feature, that has both functional and performance implications....
  4. Class object creation performance Performance aspects of Matlab class object creation are discussed, with specific suggestions. ...
 
]]>
Once again I would like to introduce guest blogger Hanan Kavitz of Applied Materials. Several months ago Hanan discussed some quirks with compiled Matlab DLLs. Today Hanan will discuss how they overcame a performance bottleneck with Matlab’s builtin rmfield function, exemplifying the general idea that we can sometimes improve performance by profiling the core functionality that causes a performance hotspot and optimizing it, even when it is part of a builtin Matlab function. For additional ideas of improving Matlab peformance, search this blog for “Performance” articles, and/or get the book “Accelerating MATLAB Performance“.

Accelerating MATLAB Performance
I’ve been using Matlab for many years now and from time to time I need to profile low-throughput code. When I profile this code sometimes I realize that a computational ‘bottleneck’ is due to a builtin Matlab function (part of the core language). I can often find ways to accelerate such builtin functions and get significant speedup in my code.

I recently found Matlab’s builtin rmfield function being too slow for my needs. It works great when one needs to remove a few fields from a small structure, but in our case we needed to remove thousands of fields from a structure containing about 5000 fields – and this is executed in a function that is called many times inside an external loop. The program was significantly sluggish.

It started when a co-worker asked me to look at a code that looked just slightly more intelligent than this:

for i = 1:5000
    myStruct = rmfield(myStruct,fieldNames{i});
end

Running this code within a tic/toc pair yielded the following results:

>> tic; myFunc(); t1 = toc
t1 =
      25.7713

In my opinion 25.77 secs for such a simple functionality seems like an eternity…

The obvious thing was to change the code to the documented faster (vectorized) version:

>> tic; myStruct = rmfield(myStruct,fieldNames); t2 = toc
t2 =
      0.6097

This is obviously much better but since rmfield is called many times in my application, I needed something even better. So I profiled rmfield and was not happy with the result.

The original code of rmfield (%matlabroot%/toolbox/matlab/datatypes/rmfield.m) looks something like this (I deleted some non-essential code for brevity):

function t = rmfield(s,field)
 
% get fieldnames of struct
f = fieldnames(s);
 
% Determine which fieldnames to delete.
idxremove = [];
for i=1:length(field)
   j = find(strcmp(field{i},f) == true);   idxremove = [idxremove;j];
end
 
% set indices of fields to keep
idxkeep = 1:length(f);
idxkeep(idxremove) = [];
 
% remove the specified fieldnames from the list of fieldnames.
f(idxremove,:) = [];
 
% convert struct to cell array
c = struct2cell(s);
 
% find size of cell array
sizeofarray = size(c);
newsizeofarray = sizeofarray;
 
% adjust size for fields to be removed
newsizeofarray(1) = sizeofarray(1) - length(idxremove);
 
% rebuild struct
t = cell2struct(reshape(c(idxkeep,:),newsizeofarray),f);

When I profiled the code, the highlighted row was the bottleneck I was looking for.

First, I noticed the string comparison equals to true part – while '==true' is not the cause of the bottleneck, it does leave an impression of bad coding style :-( Perhaps this code was created as some apprentice project, which might also explain its suboptimal performance.

The real performance problem here is that for each field that we wish to remove, rmfield compares it to all existing fields to find its location in a cell array of field names. This is algorithmically inefficient and makes the code hard to understand (just try – it took me hard, long minutes).

So, I created a variant of rmfield.m called fast_rmfield.m, as follows (again, omitting some non-essential code):

function t = fast_rmfield(s,field)
 
% get fieldnames of struct
f = fieldnames(s);
[f,ia] = setdiff(f,field,'R2012a');
 
% convert struct to cell array
c = squeeze(struct2cell(s));
 
% rebuild struct
t = cell2struct(c(ia,:),f)';

This code is much shorter, easier to explain and maintain, but also (and most importantly) much faster:

>> tic; myStruct = fast_rmfield(myStruct,fieldNames); t3 = toc
t3 =
      0.0302
 
>> t2/t3
ans =
      20.1893

This resulted in a speedup of ~850x compared to the original version (of 25.77 secs), and ~20x compared to the vectorized version. A nice improvement in my humble opinion…

The point in all this is that we can and should rewrite Matlab builtin functions when they are too slow for our needs, whether it is found to be an algorithmic flaw (as in this case), extraneous sanity checks (as in the case of ismember or datenum), bad default parameters (as in the case of fopen/fwrite or scatter), or merely slow implementation (as in the case of save, cellfun, or the conv family of functions).

A good pattern is to save such code pieces in file names that hint to the original code. In our case, I used fast_rmfield to suggest that it is a faster alternative to rmfield.

Do you know of any other example of a slow implementation in a built-in Matlab function that can be optimized? If so, please leave a comment below.

]]>
https://undocumentedmatlab.com/blog/rmfield-performance/feed 5
Secure SSL connection between Matlab and PostgreSQLhttps://undocumentedmatlab.com/blog/secure-ssl-connection-between-matlab-and-postgresql https://undocumentedmatlab.com/blog/secure-ssl-connection-between-matlab-and-postgresql#respond Fri, 18 Mar 2016 10:39:49 +0000 http://undocumentedmatlab.com/?p=6318
 
Related posts:
  1. Matlab’s internal memory representation Matlab's internal memory structure is explored and discussed. ...
  2. uiundo – Matlab’s undocumented undo/redo manager The built-in uiundo function provides easy yet undocumented access to Matlab's powerful undo/redo functionality. This article explains its usage....
  3. JMI wrapper – local MatlabControl part 2 An example using matlabcontrol for calling Matlab from within a Java class is explained and discussed...
  4. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
 
]]>
I’d like to introduce guest blogger Jeff Mandel of the Perelman School of Medicine at the University of Pennsylvania. Today Jeff will discuss a how-to guide for setting up an SSL connection between Matlab and a PostgreSQL database. While this specific topic may be of interest to only a few readers, it involves hard-to-trace problems that are not well documented anywhere. The techniques discussed below may also be applicable, with necessary modifications, to other SSL targets and may thus be of use to a wider group of Matlab users.

PostgreSQL database
I’m developing software for pharmacokinetic control, and needed secure access to a central database from users at remote sites. The client software is written in Matlab, and while I have targeted MacOS, this could be adapted to Windows fairly easily. Hopefully, this will save someone the week it took me to figure all this out.

My environment:

  • PostgreSQL 9.4 installed on the server (Windows 7 PC, but Linux would be equally good)
  • DynDNS CNAME pointing at the server (diseserver.mydomain.org)
  • CACert.org registration for domain mydomain.org
  • Matlab 2015b running on El Capitan

Here are the neccesary steps:

  1. First, we need a certificate for the server. We can generate this with OpenSSL:
    $openssl req -out diseserver.csr -new -newkey rsa:2048 -nodes -keyout diseserver.key

    Specify any information you want on the key, but ensure CN=diseserver.mydomain.org.

  2. Paste the resulting diseserver.csr file into a new key request at CACert.org. Save the resulting certificate as diseserver.crt on your machine.
  3. While still at CACert.org, grab the Class 1 root certificate and save it as root.crt.
  4. Put the files diseserver.key, diseserver.crt, and root.crt in the PostgreSQL data directory.
  5. Edit your postgresql.conf file:
    ssl = on
    ssl_cert_file = 'diseserver.crt'  # (change requires restart)
    ssl_key_file  = 'diseserver.key'  # (change requires restart)
    ssl_ca_file   = 'root.crt'        # (change requires restart)
  6. Restart the PostgreSQL server. The server will now permit SSL connections, a necessary pre-condition for certificate authentication.
  7. We now add 2 lines to pg_hba.conf:
    hostnossl  all    all   0.0.0.0/0   reject
    hostssl	 mytable  all   0.0.0.0/0   cert map=ssl clientcert=1

    The first line causes all non-SSL connections to be rejected. The second allows certificate logins for mytable using the map ssl that is defined in pg_ident.conf:

    ssl  /^(.*).mydomain\.org$ \1

    this line extracts the username prefix from CN=username.mydomain.org.

  8. Now we need to generate client certificates. PostgreSQL expects these to be in ~/.postgresql (Windows %appdata%\postgresql\):
    $mkdir ~/.postgresql
    $cd ~/.postgresql
    $openssl req -out postgresql.csr -new -newkey rsa:2048 -nodes -keyout postgresql.key

    for this key, make CN=username.mydomain.org.

  9. Again, paste the resulting postgresql.csr file into CACert.org, saving the certificate as postgresql.crt.
  10. Test this:
    $psql "sslmode=verify-full host=diseserver.mydomain.org dbname=effect user=username"

    The server should respond:

    psql (9.4.6, server 9.4.1)
    SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
  11. Next we need to convert our key into pkcs8 format so that Java can read it:
    $openssl pkcs8 -topk8 -inform PEM -outform DER -in postgresql.key -out postgresql.pk8 -nocrypt
  12. Next, ensure that we have the correct version of the JDBC driver (Java-to-database connector). From the Mac command line:
    $java -version
    java version "1.8.0_05"

    and in Matlab:

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

    This shows that although we have Java 8 installed on El Capitan (at the OS level), Matlab uses a private Java 7 version. So we need the correct version of the jdbc on our static java classpath that is used by Matlab:

    ~/Matlab/postgresql-9.4.1208.jre7.jar
  13. The next part is very poorly documented in both the MathWorks and the PostgreSQL documentation, but I found it in Russel Gray’s Basildon Coder blog: We need to use the jdbc postgresql driver to check the client certificate. To do this, we need a custom SSLSocketFactory – LibPQFactory. This will grab our certificate and key from ~/.postgresql and present them to the server. The url is (note the trailing &):
    jdbc:postgresql://diseserver.mydomain.org/mytable?ssl=true&sslfactory=org.postgresql.ssl.jdbc4.LibPQFactory&sslmode=verify-full&
  14. Next we need the username. Rather than hard-coding this in the source code, we get the system username:
    >> username = java.lang.System.getProperty('user.name');
  15. Bundle this all up in a Matlab function, stripping the trailing CR from the username:
    function dbtest
       driver = 'org.postgresql.Driver';
       [~,username] = system('whoami');
       url = 'jdbc:postgresql://diseserver.mydomain.org/mytable?ssl=true&sslfactory=org.postgresql.ssl.jdbc4.LibPQFactory&sslmode=verify-full&';
       myconn = database('mytable', username, '', driver, url);
       if ~isempty(myconn.Message)
          fprintf(2,'%s\n', myconn.Message);
       else
          fprintf(1, 'Connected!\n');
       end
    end

Now we can connect from the Matlab command line or a Matlab program.

What if we’re deployed? We also need to add the contents of our .postgresql directory, plus the jdbc jar file to our deployed app:

>> mcc -m dbtest.m -a ~/.postgresql -a ~/Matlab/postgresql-9.4.1208.jre7.jar

Let’s test the compiled program from the OS command line:

$./run_dbtest.sh /Applications/Matlab/Matlab_Runtime/v90
Connected!

Note that the key and certificates are part of the encrypted bundle produced by Matlab’s mcc compiler.

I hope this helps someone!

Yair’s note: the Matlab code above uses Matlab’s Database Toolbox (specifically, the database function) to connect to the database. In future posts I plan to show how we can connect Matlab directly to a database via JDBC. This topic is covered in detail in chapter 2 of my Matlab-Java programming secrets book.

p.s. – this blog celebrates a 7-year anniversary tomorrow: I published my very first post here on March 19, 2009, showing how to change Matlab’s command-window colors (a post that later led to the now-famous cprintf utility). It’s been a long and very interesting ride indeed, but I have no plans to retire anytime soon :-)

]]>
https://undocumentedmatlab.com/blog/secure-ssl-connection-between-matlab-and-postgresql/feed 0
Better MEX error messageshttps://undocumentedmatlab.com/blog/better-mex-error-messages https://undocumentedmatlab.com/blog/better-mex-error-messages#comments Wed, 24 Feb 2016 18:00:25 +0000 http://undocumentedmatlab.com/?p=6287
 
Related posts:
  1. Matlab mex in-place editing Editing Matlab arrays in-place can be an important technique for optimizing calculations. This article shows how to do it using Mex. ...
  2. Matlab’s internal memory representation Matlab's internal memory structure is explored and discussed. ...
  3. Undocumented Matlab MEX API Matlab's MEX API contains numerous undocumented functions, that can be extremely useful. ...
  4. Explicit multi-threading in Matlab part 3 Matlab performance can be improved by employing POSIX threads in C/C++ code. ...
 
]]>
I would like to introduce guest blogger Pavel Holoborodko, the developer of the Advanpix Multiprecision Computing Toolbox for MATLAB. Pavel has already posted here in the past as a guest blogger about undocumented Matlab MEX functions. Today he will discuss another little-known aspect of advanced MEX programming with Matlab.

MEX API provides two functions for proper handling of erroneous situations: the legacy mexErrMsgTxt and the newer mexErrMsgIdAndTxt. Both show error message, interrupt execution of a MEX module and return control to Matlab immediately.

Under the hood, these functions are implemented through C++ exceptions. The reason for this design choice is unclear. Throwing C++ exceptions across module boundary (e.g. from dynamic library to host process) is unsafe and generally considered as bad practice in software design. Exceptions are part of C++ run-time library and different versions of it might have incompatible implementations.

This restricts MEX to use only the same version of C++ run-time and GCC which were used to build that particular version of Matlab itself. This is one of the reasons why TMW distributes its own version of GCC/libstdc++ along with every release of Matlab and pushes developers to use it for MEX compilation.

Such unfortunate design decision have two unpleasant consequences:

  1. developers must use some old version of GCC (forget all the fancy stuff from C++11, C++14, etc.)
  2. compiled MEX modules most likely will not work on older/newer versions of MATLAB (re-compilation is required).

The good news is that both issues are solvable and I will write more about this in the future (it is actually possible to create single binary MEX module, which will work on any GNU Linux flavor regardless of the versions of libc/libstc++/gcc installed in the system or used in Matlab).

Here I propose just first step towards freedom – avoid direct usage of mexErrMsg** functions. Use a simple wrapper instead:

void mxShowCriticalErrorMessage(const char *msg)
{
    mxArray *arg;
    arg = mxCreateString(msg);
    mexCallMATLAB(0,0,1,&arg,"error");
}

The mxShowCriticalErrorMessage function calls Matlab’s built-in error function via the interpreter, with the error message as input parameter.

In addition to being safe, this approach potentially gives us better control over what additional information is shown together with error messages. Instead of a string, we can use an errorStruct as input argument to Matlab’s error function, with its fields tuned to our requirements (not shown here as I want to keep the example simple).

Even without tuning, output of mxShowCriticalErrorMessage is much more informative and user-friendly:

  • Error message from Matlab’s built-in functionality:

    >> A = magic(3);
    >> A(0)
    Subscript indices must either be real positive integers or logicals.

    Nice one-line message without any distracting information.
     

  • Error message from MEX using mexErrMsgTxt/mexErrMsgIdAndTxt:

    >> A = mp(magic(3));   % convert matrix to arbitrary precision type, provided by our toolbox
    >> A(0)                % subsref is called from toolbox, it is implemented in mpimpl.mex
    Error using mpimpl
    Subscript indices must either be real positive integers or logicals.
    Error in mp/subsref (line 860)
            [varargout{1:nargout}] = mpimpl(170, varargin{:});

    Intimidating four lines with actual error message lost in the middle. All the additional information is meaningless for end-user and actually misleading.

    The worst thing is that such error message is very different from what user get used to (see above one-liner), which leads to confusion if MEX plugin is properly working at all.
     

  • Error message from MEX using mxShowCriticalErrorMessage:

    >> A = magic(3);
    >> A(0)
    Error using mp/subsref (line 860)
    Subscript indices must either be real positive integers or logicals.

    Now the message is clear and short, with error description in the last line where the user focus is.
     

]]>
https://undocumentedmatlab.com/blog/better-mex-error-messages/feed 2
Quirks with compiled Matlab DLLshttps://undocumentedmatlab.com/blog/quirks-with-compiled-matlab-dlls https://undocumentedmatlab.com/blog/quirks-with-compiled-matlab-dlls#respond Wed, 10 Feb 2016 19:00:00 +0000 http://undocumentedmatlab.com/?p=6262
 
Related posts:
  1. Speeding up compiled apps startup The MCR_CACHE_ROOT environment variable can reportedly help to speed-up deployed Matlab executables....
  2. uicontextmenu performance Matlab uicontextmenus are not automatically deleted with their associated objects, leading to leaks and slow-downs. ...
  3. Transparency in uicontrols Matlab uicontrols' CData property can be customized to provide background transparency....
  4. Matlab compiler bug and workaround Both the Matlab compiler and the publish function have errors when parsing block-comments in Matlab m-code. ...
 
]]>
I would like to introduce guest blogger Hanan Kavitz of Applied Materials. Today Hanan will discuss several quirks that they have encountered with compiled Matlab DLLs.

I work for Applied Materials Israel (PDC) in the algorithm development department. My group provides Matlab software solutions across all of our products. I am a big fan of Yair’s blog and was happy to receive an invitation to be a guest blogger.

In PDC we are using Matlab compiler and Java Builder to deploy our algorithmic products at the customer sites. The software we produce includes binaries of three sorts: exe, C++ dlls, and jar files, all compiled using Matlab deployment tools.

C++ dlls are not as common and are a relatively new kind of binary in production so there’s not as much experience using them in PDC and from time to time we discover weird behaviors that might be interesting to the readers. Here are three of the latest quirks that we encountered:

Leftover tmp files

Recently I faced a problem that googling revealed that I might be the first to encounter it (outside MathWorks development team) as there was no mention of this anywhere. It all started when I got a mail from a fellow developer with content of the type: “Hi Hanan, what are these dump files for ???” and a screenshot of tempdir showing multiple tmp files that all had a naming convention of ‘mathworks_tmp_XXX_YYY’ (xxx and yyy being some numbers, presumably process ids):

multiple leftover tmp files in tmpdir (click for details)

multiple leftover tmp files in tmpdir (click for details)

Each file was about 43MB in size, and combined they consumed the entire free space in the hard-disk, preventing applications from lunching.

At first I looked in our code for the code that will produce files with this naming convention and once I was sure there is no such code I was comfortable to assume that they are MathWorks internal-use files (indeed – who other than MathWorkers would call their files mathworks_tmp_…).

Compiling and running a small ‘hello world’ C++ dll showed that every time that a Matlab-compiled C++ dll executed and ran, a temp file is created and then deleted in the %tmp% dir (tempdir). If the process that runs this dll is ‘killed’ during the run, the temp file is not deleted and remains in the %tmp% folder, accumulating over time until the hard disk becomes completely full.

On another machine I found a whole bunch of different temp files with different extensions. Opening them in editor didn’t reveal their purpose. They all had two things in common:

  1. All had a naming convention mathworks_tmp_XXX__YYY, whatever the extension of the file may be.
  2. They are all useless when the Matlab application is done running.

Once this was clear, the solution was very simple:

  • When lunching the process that runs Matlab compiled dll, change the %tmp% directory to a new one.
  • Delete this directory once done running or on the next process start.

mclInitializeApplication

As a separate discussion, our compiled algorithm is embarrassingly parallel in nature so our C++ team is running it in parallel processes across several machines and many cores.

As with all Matlab-compiled C++ DLLs, it needs to be initialized with a call to mclInitializeApplication per running process. This worked well when we had a relatively small number of processes running concurrently but lately we encountered a problem that out of dozens of calls to this function from time to time a call is stuck (not failed – exactly that: stuck) and the process needs to be killed.

We don’t know why this happens and the solution we are currently using is pretty “shaky” at best – we retry the call to this function several times until it eventually works (and it does work after several tries).

I have a suspicion that something is not entirely parallel with this function and there exists some hidden internal shared resource among different processes but no way to know exactly as this is an internal MathWorks function.

Implicit multithreading

This is relatively old issue we encountered at the beginning when we just started using Matlab-compiled DLLs, so this might not surprise some readers. While Matlab’s builtin (automatic) multithreading is great when used in the MATLAB IDE (non-compiled), it creates a problem when running compiled DLLs in parallel across multiple processes: this multithreading ‘starves’ for cores because they are busy at running other processes.

The solution is simple and well documented – when calling mclInitializeApplication before launching the DLL, pass it the singleCompThread flag to prevent implicit multithreading. We found this single threaded DLL to run faster because it reduced CPU ‘starvation’ drastically in a multi process environment.

Addendum (by Yair again):

I am delighted to announce that a few days ago I received an apparently-automated email from MathWorks telling me that 4 of the issues that I have reported early last year were fixed in R2015b. IMHO, this marks a very important step of closing the loop with the original issue reporter, something that I have suggested publicly back in December 2014 (and also privately over the years). I believe that such automated feedbacks increase user motivation to report misbehaving or missing features, which will ultimately make Matlab better for the benefit of us all. I also believe that this proves once again my claim that beneath the corporate jargon, MathWorks is indeed a company run by engineers like us, who cares about its users and the interaction with them more than typical in the corporate world. I can only praise this email and hope that it is now part of the ongoing development release process, rather than being an isolated case. If I may suggest a followup improvement, it would be nice to receive such emails before the new release is out (i.e., during the beta phase) so that the original reporter could have a chance to test it on the beta before it actually goes live. But in any case, thanks MathWorks for listening and making yet another improvement :-)

Happy New Year of the Monkey everybody!

]]>
https://undocumentedmatlab.com/blog/quirks-with-compiled-matlab-dlls/feed 0
Graphic sizing in Matlab R2015bhttps://undocumentedmatlab.com/blog/graphic-sizing-in-matlab-r2015b https://undocumentedmatlab.com/blog/graphic-sizing-in-matlab-r2015b#comments Wed, 20 Jan 2016 18:00:31 +0000 http://undocumentedmatlab.com/?p=6244
 
Related posts:
  1. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
  2. Modifying default toolbar/menubar actions The default Matlab figure toolbar and menu actions can easily be modified using simple pure-Matlab code. This article explains how....
  3. FIG files format FIG files are actually MAT files in disguise. This article explains how this can be useful in Matlab applications....
  4. A couple of internal Matlab bugs and workarounds A couple of undocumented Matlab bugs have simple workarounds. ...
 
]]>
I would like to introduce Daniel Dolan of Sandia National Laboratories. Dan works on a variety of data analysis projects in Matlab, and is an active lurker on MATLAB Central. Dan has a habit of finding interesting bugs for the Mac version of Matlab. Today he will discuss graphic sizing in Matlab and important changes that occurred in release R2015b.

Matlab-generated graphics are often not displayed at their requested size. This problem has been known for some time and has a well-known solution: setting the root object’s ScreenPixelsPerInch property to the display’s actual DPI (dots per inch) value. Release R2015b no longer supports this solution, creating problems for publication graphics and general readability.

Physical sizing in R2015a vs. R2015b (click for full-size)

Physical sizing in R2015a vs. R2015b (click for full-size)


Physical sizing

Matlab supports graphic sizing in various physical units: inches, centimeters, and points. For example:

figure; axes('Box','on', 'Units','inches','Position',[0.3 0.3 4 4]);

requests to display an axes having square sizes measuring exactly 4″ (101.6 mm) each. It is evident, however, that the displayed axes is smaller than 4″. The mismatch between requested and physical size depends on the display and operating system — go ahead, try it on your system. The problem is particularly severe on Mac laptops, presumably even worse for those with Retina displays.

The problem is that Matlab cannot determine pixel size, which varies from one display to the other. Generating a figure spanning a particular number of pixels (e.g., 1024 x 768) is easy, but absolute physical units requires a conversion factor called ScreenPixelsPerInch, which is a root property (see related post on setting/getting default graphics property values):

DPI = 110;                             % dots per inch for my 27" Apple Cinema Display
set(0,    'ScreenPixelsPerInch',DPI);  % all releases prior to R2015b
set(groot,'ScreenPixelsPerInch',DPI);  % R2014b through R2015a

DPI values tend to be higher for laptops, usually in the 120-130 range. Retina displays are supposed to be >300 DPI, but I have not been able to test that myself.

There are several ways to determine the correct DPI setting for a particular display. It may be available in the hardware specifications, and it can be calculated from the diagonal size and the number of pixels. Unfortunately these methods are not always reliable. If you really care about physical sizing, the best approach is to actually calibrate your display. There are tools for doing this at Matlab Central, but it’s not hard to do manually:

  • Create a figure.
  • Manually resize the figure to match a convenient width. I often use a piece of US letter paper as 8.5″ guide on the display.
  • Determine the width of the figure in pixels:
    set(gcf,'Units','pixels');
    pos = get(gcf,'Position');
    width = 8.5; % inches
    DPI = pos(3) / width;

I usually apply the DPI settings in my startup file so that Matlab begins with a calibrated display.

What changed in 2015b?

ScreenPixelsPerInch is a read-only property in R2015b, so display calibration no longer works. The following sequence of commands:

figure('Units','inches', 'PaperPositionMode','auto', 'Position',[0 0 4 4]);
set(gcf, 'MenuBar','none', 'ToolBar','none', 'DockControls','off', 'NumberTitle','off');
axes('FontUnits','points', 'FontSize',10);
image

now renders differently in R2015b than does for a calibrated display in R2015a. Differences between the two outputs are shown in the screenshot at the top of this post. The grid behind the figures was rendered at 8.5″ x 8.5″ inches on my display; if your browser’s zoom level isn’t 100%, it may appear larger or smaller.

A side effect of improper graphic sizing is that text is difficult to read — the uncalibrated axes labels are clearly smaller than 10 points. These examples were rendered on ~110 DPI display. Matlab assumes that Macs use 72 DPI (96 DPI on Windows), so graphics appear at 65% of the request size.

The loss of ScreenPixelsPerInch as an adjustable setting strongly affects anyone using Matlab for publication graphics. Scientific and engineering journals are extremly strict about figure widths. With a calibrated screen, figure appear exactly as they will when printed to a file (usually EPS or PDF). Figures are often made as small as possible to and densely packed to save journal space, and accurate sized display helps the author determine legibility. Displaying accurately sized graphics is very difficult in R2015b, which is unfortunate given the many enhancements in this release.

Developers who create graphical interfaces for other users should also care about this change. A common complaint I get is that text and control labels is too small to easily read. Screen calibration deals with this problem, but this option is no longer available.

Where do we go from here?

I reported the above issues to the Mathworks several months ago. It does not appear as a formal bug, but technical support is aware of the problem. The change is part of the “DPI aware” nature of release R2015b. So far I have found no evidence this release is any more aware of pixel size than previous releases, but my experience is limited to non-Retina Macs. I welcome input from users on other operating systems, particularly those with high-resolution displays.

To be fair, correct physical sizing is not an easy across the many platforms that Matlab runs on. Display resolution is particularly tricky when it changes during a Matlab session, such as when computer is connector to projector/television or a laptop is connected to a docking station.

Thankfully, printed graphic sizes are rendered correctly when a figure’s PaperPositionMode property is 'auto'. Many users can (and will) ignore the display problem if they aren’t dealing with strict size requirements and text legibility isn’t too bad. Some users may be willing to periodically print publication figures to externally verify sizing, but this breaks the interactive nature of Matlab figures.

A potential work around is the creating of a new figure class that oversizes figures (as needed) to account for a particular display. I started working on such a class, but the problem is more complicated than one might think:

  • Child objects (axes, uicontrols, etc.) also must be resized if they are based on physical units.
  • Resized objects must be temporarily restored to their original size for printing, and new objects must be tracked whenever they are added.
  • Figure resolution may need to be changed when moving to different computer systems.

These capabilities are quite possible to implement, but this is a complicated solution to problem that was once easy to fix.

Retina displays don’t suffer as badly as one might think from the DPI mismatch. Even though the display specification may be greater than 200 DPI, OS X and/or Matlab must perform some intermediate size transformations. The effective DPI in R2015a is 110-120 for 13-15″ MacBook Pro laptops (at the default resolution). Objected sized with physical units still appear smaller than they should (~72/110), but not as small as I expected (<72/200).

Effect pixel size can also be changed by switching between different monitor scalings. This isn’t entirely surprising, but it can lead to some interesting results because Matlab only reads these settings at startup. Changing the display scaling during a session can cause square figures to appear rectangular. Also, the effective DPI changes for setting: I could reach values of ~60-110 DPI on an Apple Cinema Display.

So where does this leave us? Display calibration was always a finicky matter, but at least in principle one could make graphics appear exactly the same size on two different displays. Now it seems that sizing is completely variable between operation systems, displays, and display settings. For publication graphics, there will almost always be a disconnect between figure size on the screen and the printed output; some iteration may be needed to ensure everything looks right in the finished output. For graphical interfaces, font sizes may need to generated in normalized units and then converted to pixels (to avoid resizing).

Physical accuracy may not be important for non-publication figures, but the issue of text legibility remains. Some text objects–such as axes and tick labels–can easily be resized because the parent axes automatically adjusts itself as needed. Free floating text objects and uincontrols are much more difficult to deal with. Controls are often sized around the extent of their text label, so changing font sizes may require changes to the control position; adjacent controls may overlap after resizing for text clarity. Normalized units partially solve this problem, but their effect on uicontrols is not always desirable: do you really want push buttons to get larger/smaller when the figure is resized?

Can you think of a better workaround to this problem? If so, then please post a comment below. I will be very happy to hear your ideas, as I’m sure others who have high resolution displays would as well.

(cross-reference: CSSM newsgroup post)

Addendum Dec 31, 2016: Dan Dolan just posted a partial workaround on the MathWorks File Exchange. Also see the related recent article on working with non-standard DPI values.

]]>
https://undocumentedmatlab.com/blog/graphic-sizing-in-matlab-r2015b/feed 8
Capturing print eventshttps://undocumentedmatlab.com/blog/capturing-print-events https://undocumentedmatlab.com/blog/capturing-print-events#comments Wed, 08 Jul 2015 18:00:30 +0000 http://undocumentedmatlab.com/?p=5909
 
Related posts:
  1. Figure keypress modifiers The figure's CurrentModifier property provides a simple and consistent way to retrieve keypress modifiers: alt-, control- and shift-clicks. ...
  2. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
  3. Docking figures in compiled applications Figures in compiled applications cannot officially be docked since R2008a, but this can be done using a simple undocumented trick....
  4. Customizing figure toolbar background Setting the figure toolbar's background color can easily be done using just a tiny bit of Java magic powder. This article explains how. ...
 
]]>
As a followup to my recent post on capturing and using HG2’s new graphic events, I would like to welcome back guest blogger Robert Cumming, who developed a commercial Matlab GUI framework. Today, Robert will highlight an unusual use of event listeners to enable print output customizations by tapping into print-related events.

One of my toolbox clients wanted to ensure that every print-out, of any Matlab GUI, would contain a datestamp footer and a project id header.

Initially I thought this would be a simple task, since the GUI framework already has saveAs and copyToClipboard methods that users could utilize. Moreover, as Yair has shown some years ago, we can easily adapt the standard callbacks associated with the Matlab figure toolbar’s <Print> button and the menu-bar’s Print action. We can even customize the standard print setup. However, all this does not help when directly invoking printout commands from the Matlab command line or from within the user program, for example:

% Create the GUI
[x,y,z] = peaks(75); 
surf(x,y,z);
 
% printout via print() or export_fig
print(gcf, .... )
export_fig filename  % see https://undocumentedmatlab.com/blog/export_fig

Printout with the expected header and footer stamps

Printout with the expected header and footer stamps


This initially posed a bit of a challenge – how could I capture the print event?

The key to solving this was using events in a different way. Rather than listen for a print event, we listen for something that print interacts with in the figure window. This will solve the problem for both print and export_fig, since export_fig uses print internally.

We can listen to get and set events on many Matlab properties. In this instance we can trap get events on a figure’s PaperPositioMode, or PaperSize property. print, saveas and export_fig all access these properties before doing the actual printing, so by trapping the event we can run our own function before the printing is done. For example:

classdef PrintListenerDemo
  properties
    referenceNo = 'R1234-56'
  end
 
  methods (Access=public)
    function obj = PrintListenerDemo
      hFig = figure;
      [x,y,z] = peaks(75);
      surf ( x, y, z );
 
      % add listener on event to prepare the figure for printing
      addlistener ( hFig, 'PaperPositionMode', 'PreGet', @obj.Prep );
 
      % Testing only:
      evalin ( 'base', 'print ( gcf, ''-dmeta'' )' );  % simulate user action in command-line
      print(hFig,'-dmeta');    % simulate programmatic printout
    end
 
    function Prep(obj, hFig, varargin)
      disp ( 'running function in preparation for printing.' );
 
      % Add datestamp and reference id UIControls
      str = sprintf ( 'Printed @ %s', datestr(now) );
      uicontrol ( 'parent',hFig, 'style','text', 'units','normalized', ...
                  'position',[0 0 1 0.07], 'string',str, 'BackgroundColor','white' );
    end
  end
end

When we run the above we can see that the disp message is displayed twice, because the property has two get calls in the print function. We can easily solve this by saving a temp variable that is created the first time it is run.

The next thing we need to do is to clean up afterwards, i.e. remove the uicontrols and reset the temp variable to ensure that any future print events are captured.
Here you might think the second get call I mentioned above was post printing, but it’s not. So we need to capture another event to do the cleaning up.

In this instance I thought about what was likely to happen – some sort of user interaction, e.g. a mouse move, press or key press. So we can listen for any of those events and run our clean up method. This is shown in the full code below:

% PrintListenerDemo - Demo of print listener methodology
classdef PrintListenerDemo
  properties
    referenceNo = 'R1234-56'
  end
 
  methods (Access=public)
    function obj = PrintListenerDemo
      hFig = figure;
      [x,y,z] = peaks(75);
      surf ( x, y, z );
 
      % add listener on event to prepare the figure for printing
      addlistener ( hFig, 'PaperPositionMode', 'PreGet', @obj.Prep );      
 
      % add a few different ways to clean up
      addlistener ( hFig, 'ButtonDown', @obj.CleanUp );
      addlistener ( hFig, 'WindowKeyPress', @obj.CleanUp );
      addlistener ( hFig, 'WindowMouseMotion', @obj.CleanUp );
 
      % Testing only:
      evalin ( 'base', 'print ( gcf, ''-dmeta'' )' );  % simulate user action in command-line
      print(hFig,'-dmeta');    % simulate programmatic printout
    end
 
    function Prep(obj, hFig, varargin)
      try
        hFig.ApplicationData.printPrepDone;
        return % If variable set do not run this method again
      end
      disp ( 'preparing for print.' );
 
      % create the date string
      str1 = sprintf ( 'Printed @ %s', datestr(now) );
      str2 = sprintf ( 'Reference: %s', obj.referenceNo );
 
      % create 2 UI controls to contain the information requested in the image
      hFig.ApplicationData.UIC1 = uicontrol ( 'parent',hFig, 'style','text', 'units','norm', 'string',str1, 'BackgroundColor','w', 'position',[0 0 1 0.07] );
      hFig.ApplicationData.UIC2 = uicontrol ( 'parent',hFig, 'style','text', 'units','norm', 'string',str2, 'BackgroundColor','w', 'position',[0 0.93 1 0.07] );
 
      % Save a temp variable to stop this function being called many times.
      hFig.ApplicationData.printPrepDone = true;
    end
 
    function CleanUp(obj, hFig, varargin)
      try
        if hFig.ApplicationData.printPrepDone
          % Clean up the uicontrols
          disp ( 'clean up post printing event' );
          delete ( hFig.ApplicationData.UIC1 );
          delete ( hFig.ApplicationData.UIC2 );
 
          % remove the temp variable, so the next print job will be captured
          hFig.ApplicationData = rmfield ( hFig.ApplicationData, 'printPrepDone' );
        end
      end
    end
  end
end

It is noted here that the datestamp and the reference number remain visible until the user interacts with the GUI but that’s a small price to pay.

Any suggestions on other ways to clean up the print event afterwards? If so, please post a comment below. Alternatively if you have used events and listeners in an unusual way please share this as well.

Conclusions

  1. It is possible to capture printout events in your code even when the print command is invoked programmatically, without a direct reference to your code
  2. We can use events for things that we might never have initially considered
]]>
https://undocumentedmatlab.com/blog/capturing-print-events/feed 3
JGraph in Matlab figureshttps://undocumentedmatlab.com/blog/jgraph-in-matlab-figures https://undocumentedmatlab.com/blog/jgraph-in-matlab-figures#comments Wed, 01 Jul 2015 18:00:23 +0000 http://undocumentedmatlab.com/?p=5895
 
Related posts:
  1. GUI automation using a Robot This article explains how Java's Robot class can be used to programmatically control mouse and keyboard actions...
  2. GUI automation utilities This article explains a couple of Matlab utilities that use Java's Robot class to programmatically control mouse and keyboard actions...
  3. 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....
  4. Adding a context-menu to a uitree uitree is an undocumented Matlab function, which does not easily enable setting a context-menu. Here's how to do it....
 
]]>
I would like to introduce guest blogger Scott Koch. Scott is part of the development team at Eigenvector Research Inc., makers of PLS_Toolbox, a commercial chemometrics and multivariate data analysis toolbox. Today Scott will expand on JGraph, a Java-based open source graph visualization and diagramming library.

What is JGraph?

JGraph is an interactive Java-based diagramming and graph visualization library. The maintainers of JGraph have a product family that includes a Java Swing library (open-source), a JavaScript library (proprietary commercial), as well as other technologies. They call their product family “mxGraph”, and the Swing product specifically as “JGraphX”. The Swing library is available on GitHub and licensed under BSD. I will refer to the Swing library as JGraph, since that was the original library’s name until it was completely redesigned some years ago and renamed JGraphX. You can read additional information on JGraph and access various documentation alternatives in its README file.

Graphing is a powerful visualization tool that has not yet been integrated into the core Matlab product. I assume that this will be rectified by MathWorks in a future Matlab release. But until that time, or even later if you are still using R2015a or older, we do not have a solution in the core Matlab. In our toolbox product, we use a cleverly designed image to display a simple diagram, but I always thought it would be nice to have a “real” diagramming tool that was interactive and full-featured.

So, as a long time follower of Yair’s blog, I was thrilled to see his post several years ago about integrating Java libraries for charting and diagramming in Matlab figures. Unfortunately, my first attempts at getting JGraph to work in Matlab were not very successful. Thanks to a comment on that original post by Markus Behle, I was able to gain full access to JGraph in Matlab. Today’s post will show how we can use JGraph in Matlab.

Creating a new JGraph edge in a Matlab figure

Creating a new JGraph edge in a Matlab figure


Creating a simple graph

To install JGraph, first download the JGraph zip file, extract it in some folder, and then add the contained JGraph jar file to your Matlab’s Java path:

javaaddpath('jgraphx/lib/jgraphx.jar');

Having installed JGraph, we can now create graphs pretty easily in Matlab – see Yair’s original post for details.

Unfortunately, dragging doesn’t work and that’s a bummer. To enable dragging, create a custom graph component. I posted a followup comment showing how to do this. Note that the following code will work without creating a custom graph component but you won’t be able to drag (and drop).

In JGraph, a graph is made up of cells. A cell can be a vertex (node) or edge (connector). A cell can also hold other cells in a group.

Below is a code snippet similar to Yair’s original JGraph post, except we’ll use the custom graph component from above and add an additional vertex:

% Make the graph object
graph = javaObjectEDT('mymxGraph’);
 
% If not using custom graph component use the following
% graph = javaObjectEDT('com.mxgraph.view.mxGraph');
 
% Get the parent cell
parent = graph.getDefaultParent();
 
% Group update
graph.getModel().beginUpdate();
 
% Add some child cells
v1 = graph.insertVertex(parent, '', 'Hello', 240, 150, 80, 30);
v2 = graph.insertVertex(parent, '', 'World',  20,  20, 80, 30);
v3 = graph.insertVertex(parent, '', 'Vertex', 20, 150, 80, 30);
graph.insertEdge(parent, '', 'Edge', v1, v2);
 
graph.getModel().endUpdate();
 
% Get scrollpane
graphComponent = com.mxgraph.swing.mxGraphComponent(graph);
 
% Make a figure and stick the component on it
f = figure('units','pixels');
pos = get(f,'position'); 
mypanel = javax.swing.JPanel(java.awt.BorderLayout);
mypanel.add(graphComponent);
[obj, hcontainer] = javacomponent(mypanel, [0,0,pos(3:4)], f);
 
% Normalize units so resize works better
set(hcontainer,'Units','normalized');

We have 3 vertices and a single edge connecting two vertices. Each has a label. By default you can edit the labels and drag the vertices and edges. If you mouse over the middle of a vertex it will highlight, indicating that if you click and drag, you will be able to add an edge. Dragging the edge to another vertex will connect it. You can also resize and reposition vertices, as well as set edge labels, as shown in the animated image above.

Customizing graphs with HTML and CSS

If you look at online examples of JGraph, you can see there are lots of options for customizing your graph’s appearance. JGraph uses “styles” on vertices and edges, which are similar in concept to Cascading Style Sheets (CSS). You can add style information when you create a vertex, or by using the Graph Model. Rerun the code above with the following lines substituted:

v1 = graph.insertVertex(parent, '', 'Hello', 240, 150, 150, 150, 'rounded=1;');
v2 = graph.insertVertex(parent, '', 'World',  20,  20,  80,  30, 'rounded=1;strokeColor=blue;fillColor=lightblue');
v3 = graph.insertVertex(parent, '', 'Vertex', 20, 150,  80,  30, 'rounded=1;strokeColor=#000000;fillColor=#00CCFF;gradientColor=#333300;fontColor=white');
graph.insertEdge(parent, '', 'Edge', v1, v2, 'edgeStyle=elbowEdgeStyle;strokeColor=#5d65df;strokeWidth=2');

Simple JGraph with new styles

Simple JGraph with new styles

As Yair has taught us, most Java controls can render HTML. JGraph is no different, you just need to turn it on and add HTML to your label:

>> graph.setHtmlLabels(true);
>> htmltxt = ['<html><b>My HTML Vertex</b><hr noshade size=''3''>'...
              '<table border=1 cellspacing=1 cellpadding=5 '...
              'font color="#0000FF" FONT COLOR="black">'...
              '<tr><td><b>Style</b></td><td><b>Value</b></td></tr>'...
              '<tr><td>rounded</td><td>1</td></tr>'...
              '<tr><td>fillColor</td><td>yellow</td></tr>'...
              '</table></html>'];
>> v1.setValue(htmltxt)
>> graph.refresh

Vertex with HTML label

Vertex with HTML label

Adding a callback

Let’s add more functionality to our graph by adding a callback. To do this, we need to add a mouse-clicked callback to the graph scrollpane:

% Handle the scrollpane and add a click callback
scrollpanehandle = handle(graphComponent.getGraphControl, 'CallbackProperties');
set(scrollpanehandle, 'MouseClickedCallback', {@mouseClickCallback,f})

With a click callback in place, we can interrogate the click event and graph to determine what object is under the click. If the click happens over a vertex, a context menu is displayed allowing changing of the fill color.

function mouseClickCallback(Obj,eventData,myFig)
   %Graph mouse click callback
 
   %Extract graph object
   graphcomponent = Obj.getGraphContainer;
   graph = graphcomponent.getGraph;
   figpos = get(myFig,'position');
 
   %Get cell under click if it's there
   mycell = graphcomponent.getCellAt(eventData.getX,eventData.getY);
 
   if isempty(mycell) || mycell.isEdge
      %Clicking in open space
      return
   end
 
   if javax.swing.SwingUtilities.isRightMouseButton(eventData)
      mymenu = findobj(myFig,'tag','backgroundmenu');
      if isempty(mymenu)
         %Create context menu
         mymenu = uicontextmenu('tag','backgroundmenu');
         uimenu(mymenu,'Tag','graymenu','Label','Gray Background');
         uimenu(mymenu,'Tag','bluemenu','Label','Blue Background');
      end
 
      %Update callback with current cell object
      set(findobj(mymenu,'tag','graymenu'),'callback',{@changeFillColor,graph,mycell,'gray'});
      set(findobj(mymenu,'tag','bluemenu'),'callback',{@changeFillColor,graph,mycell,'blue'});
 
      %Show context menu
      set(mymenu,'position', [eventData.getX+8 figpos(4)-eventData.getY-8]);
      set(mymenu,'visible','on');
   end
end
 
function changeFillColor(Obj,eventData,varargin)
   % Change cell fill color
 
   %Pull graph object, current cell object, and new color value out of varargin
   mygraph = varargin{1};
   mycell = varargin{2};
   newcolor = varargin{3};
 
   %Get current style
   mystyle = char(mycell.getStyle);
 
   %Chop string into cells and locate fillcolor cell
   stylecell = strsplit(mystyle,';');
   fcloc = ~cellfun('isempty',strfind(stylecell,'fillColor='));
 
   %Make new fillcolor string
   switch newcolor
      case 'gray'
         newcolor = 'fillColor=#E8E8E8';
      case 'blue'
         newcolor = 'fillColor=#A9BCF5';
   end
 
   %Add new color into style
   if any(fcloc)
      stylecell{fcloc} = newcolor;
   else
      stylecell{end+1} = newcolor;
   end
 
   %Join styles back into single style string
   mystyle = strjoin(stylecell,';');
 
   %Set new style
   mygraph.getModel.setStyle(mycell,mystyle);
end

Conclusions

Hopefully this post gave enough information to get started making attractive and useful graphs with Matlab and JGraph. There is a lot of functionality included with JGraph and we’ve only scratched the surface today. I hope to have a future post discussing Groups, Drag and Drop, Layout Engines, and a few other topics that build upon what was discussed today.

Here are a few resources that could help you get started:

Addendum September 4, 2015: Matlab R2015b has just been released and includes very interesting new functionality supporting graph algorithms and visualization (additional details).

]]>
https://undocumentedmatlab.com/blog/jgraph-in-matlab-figures/feed 4
copyobj behavior change in HG2https://undocumentedmatlab.com/blog/copyobj-behavior-change-in-hg2 https://undocumentedmatlab.com/blog/copyobj-behavior-change-in-hg2#respond Wed, 13 May 2015 16:00:49 +0000 http://undocumentedmatlab.com/?p=5797
 
Related posts:
  1. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
  2. Performance: accessing handle properties Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
  3. uicontextmenu performance Matlab uicontextmenus are not automatically deleted with their associated objects, leading to leaks and slow-downs. ...
  4. Graphic sizing in Matlab R2015b Matlab release R2015b's new "DPI-aware" nature broke some important functionality. Here's what can be done... ...
 
]]>
As a followup to last-week’s post on class-object and generic data copies, I would like to welcome back guest blogger Robert Cumming, who developed a commercial Matlab GUI framework. Today, Robert will highlight a behavior change of Matlab’s copyobj function in HG2.

One of the latest features that was introduced to the GUI Toolbox was the ability to undock or copy panels, that would be displayed in a standalone figure window, but remain connected to the underlying class object:

Panel copy in the GUI framework toolbox

Panel copy in the GUI framework toolbox

These panel copies had to remain fully functional, including all children and callbacks, and they needed to retain all connections back to the source data. In the example above I have altered the plot to show that it’s an actual copy of the data, but has separate behavior from the original panel.

To simply undock a uipanel to a new figure, we can simply re parent it by updating its Parent property to the new figure handle. To make a copy we need to utilize the copyobj function, rather than re-parenting. copyobj can be used to make a copy of all graphic objects that are “grouped” under a common parent, placing their copy in a new parent. In HG2 (R2014b onwards) the default operation of copyobj has changed.

When I started developing this feature everything looked okay and all the objects appeared copied. However, none of the callbacks were functional and all the information stored in the object’s ApplicationData was missing.

I had used copyobj in the past, so I knew that it originally worked ok, so I investigated what was happening. Matlab’s documentation for HG2 code transition suggests re-running the original code to create the second object to populate the callbacks. Unfortunately, this may not be suitable in all cases. Certainly in this case it would be much harder to do, than if the original callbacks had been copied directly. Another suggestion is to use the new ‘lagacy’ option’:

copyobj(___,’legacy’) copies object callback properties and object application data. This behavior is consistent with versions of copyobj before MATLAB® release R2014b.

So, instead of re-running the original code to create the second object to populate the callbacks, we can simply use the new ‘legacy’ option to copy all the callbacks and ApplicationData:

copyobj(hPanel, hNewParent, 'legacy')

Note: for some reason, this new ‘legacy’ option is mentioned in both the doc page and the above-mentioned HG2 code-transition page, but not in the often used help section (help copyobj). There is also no link to the relevant HG2 code-transition page in either the help section or the doc page. I find it unfortunate that for such a backward-incompatible behavior change, MathWorks has not seen fit to document the information more prominently.

Other things to note (this is probably not an exhaustive list…) when you are using copyobj:

  • Any event listeners won’t be copied
  • Any uicontextmenus will not be copied – it will in fact behave strangely due to the fact that it will have the uicontextmenu – but the parent is the original figure – and when you right-click on the object it will change the figure focus. For example:
    hFig= figure;
    ax = axes;
    uic = uicontextmenu ('parent', hFig);
    uim = uimenu('label','My Label', 'parent',uic);
    ax.UIContextMenu = uic;
     
    copyChildren = copyobj (ax, hFig, 'legacy');
     
    hFig2 = figure;
    copyChildren.Parent = hFig2;

Another note on undocked copies – you will need to manage your callbacks appropriately so that the callbacks manage whether they are being run by the original figure or in a new undocked figure.

Conclusions

  1. copyobj has changed in HG2 – but the “legacy” switch allows you to use it as before.
  2. It is unfortunate that backward compatibility was not fully preserved (nor documented enough) in HG2, but at least we have an escape hatch in this case.
  3. Take care with the legacy option as you may need to alter uicontextmenus and re-attach listeners as required.
]]>
https://undocumentedmatlab.com/blog/copyobj-behavior-change-in-hg2/feed 0
Simulink Data Dictionaryhttps://undocumentedmatlab.com/blog/simulink-data-dictionary https://undocumentedmatlab.com/blog/simulink-data-dictionary#comments Wed, 11 Feb 2015 18:00:11 +0000 http://undocumentedmatlab.com/?p=5571
 
Related posts:
  1. Creating a simple UDD class This article explains how to create and test custom UDD packages, classes and objects...
  2. UDD Properties UDD provides a very convenient way to add customizable properties to existing Matlab object handles...
  3. UDD Events and Listeners UDD event listeners can be used to listen to property value changes and other important events of Matlab objects...
  4. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
 
]]>
Once again I wish to welcome guest blogger Donn Shull. Donn has previously written a series of articles on Matlab’s previous-generation class-object system (UDD). Today Donn explores a little-known yet quite useful aspect of Simulink.

Introduction

In 2014, MathWorks introduced the Simulink Data Dictionary. This new feature provides the ability to store Data Types, Parameters, and Signals in database files. This is great news for embedded systems developers who want the flexibility of using data objects and want to avoid using the base workspace with its potential for data corruption.

In its initial implementation, the data dictionary interface is provided by the Simulink Model Explorer. The GUI interface is clean, intuitive, and easy to use. This interface supports importing and exporting dictionaries to m files and mat files.

Unfortunately, in production code generation environments there is frequently a need to interface this data with external tools such as software specification systems, documentation generators, and calibration tools. MathWorks have not published an API for accessing dictionaries from code, indicating that it may possibly be available in a future release. Today, we will look at some portions of the undocumented API for Simulink Data Dictionaries.

Simulink F14 model using data dictionary

Some background information

Simulink Data Dictionaries exist as files having a standard file extension of .sldd. Dictionary files can be opened with the open function, which in turn calls opensldd. This opens the file and launches the Simulink Model Explorer with the selected dictionary node. When a dictionary is opened, a cached copy is created. While working with a dictionary, changes are made to the cached copy. The dictionary file is only changed when the changes are saved by issuing the relevant command. Until the cached copy is saved, it is possible to view differences between the file and the cached copy, and revert any unwanted changes. The file maintains the date, time, and author of the last saved change, but no information about previous revisions.

From the Model Explorer it is possible to add items to a dictionary from a model, the base workspace, or by creating new items. We can associate a Simulink model with a dictionary by using the model properties dropdown in the Simulink editor.

Using data dictionaries it is possible to tailor a model’s code generation for different targets, simply by changing the dictionary that is being used.

The Simulink Data Dictionary API

Programmatic access to Simulink Data Dictionaries is provided by the undocumented MCOS package Simulink.dd. We will look at two package functions and a few methods of the Simulink.dd.Connection class. These provide the basic ability to work with dictionaries from within our m code.

Creating and Opening Dictionary Files

Dictionary files are created with the package function create:

hDict = Simulink.dd.create(dictionaryFileName);

Existing dictionary files are opened using the package function open:

hDict = Simulink.dd.open(dictionaryFileName);

In both cases the functions return a handle of type Simulink.dd.Connection to the named dictionary file.

Modifying a Dictionary

We can use methods of the Simulink.dd.Connection instance to modify an open dictionary. Dictionaries are organized into two sections: The Configurations section contains Simulink.ConfigSet entries, while Parameter, Signal, and DataType items are placed in the Global section. We can get a list of the items in a section using the getChildNames method:

childNamesList = hDict.getChildNames(sectionName);

Adding and removing items from a section are done using the insertEntry and deleteEntry methods, respectively:

hDict.insertEntry(sectionName, entryName, object)
hDict.deleteEntry(sectionName, entryName)

Modifying an existing entry is done using the getEntry, and setEntry methods:

workingCopy = hDict.getEntry(sectionName.entryName)
 
% modify workingCopy
hDict.setEntry(sectionName.entryName, workingCopy)

A collection of objects from the base workspace can be added to a dictionary using the importFromBaseWorkspace method:

hDict.importFromBaseWorkspace(sectionName, overwriteExisitngObjectsFlag, deleteFromBaseWorkspaceFlag, cellArrayOfNames)

Additional dictionary manipulations are possible using the evalin and assignin methods:

hDict.evalin(commandString)
hDict.assignin(variableName, variable)

Closing a Dictionary

Finalizing a dictionary session is done with the saveChanges, close, and delete methods:

hDict.saveChanges
hDict.close
hDict.delete

Example: Migrate Single Model to Use Dictionary

This example is an adaptation of MathWorks’ interactive example of the same title, using programmatic Matlab m commands rather than GUI interactions.

  1. Start by using load_system to open the f14 model. This opens the model and executes the PreLoadFcn callback, which loads design data into the base workspace, without opening the Simulink block diagram editor:
    load_system('f14');
  2. Use the Simulink package function findVars to find the variables used by the model:
    usedVariables = Simulink.findVars('f14');
  3. Next, use the create package function to create and open a new Simulink Data Dictionary:
    hDict = Simulink.dd.create('f14_data_dictionary.sldd');
  4. Attach the newly created dictionary to the model:
    set_param('f14', 'DataDictionary', 'f14_data_dictionary.sldd');
  5. Use one of the API methods to add these variables to the Data Dictionary:
    overWrite = true;
    deleteFromWorkspace = false;
    for n = 1:numel(usedVariables)
        if strcmp(usedVariables(n).Source, 'base workspace')
            hDict.importFromBaseWorkspace(overWrite, deleteFromWorkspace, {usedVariables(n).Name});
        end
    end
  6. Save the changes made to the dictionary:
    hDict.saveChanges;
  7. Clean up and we are done:
    hDict.close;
    hDict.delete;
    clear hDict;

Final notes

MathWorks have recognized the value of data dictionaries for a long time. In 2006, MathWorker Tom Erkkinen published a paper about multitarget modeling using data dictionaries. The Simulink.dd package was added to Matlab in R2011b, and the DataDictionary parameter was added to Simulink models in R2012a. MathWorks have also indicated that a user API for Simulink Data Dictionaries may be in the works. Until it is released we can make do with the undocumented API.

Update March 7, 2015: Matlab release R2015a now includes a fully documented Simulink.data.Dictionary class, which works in a very similar manner. Users of R2015a or newer should use this new Simulink.data.Dictionary class, while users of previous Matlab releases can use the Simulink.dd class presented in this article.

Have you made some good use of this data-dictionary functionality in your project? If so, please share your experience in a comment below.

]]>
https://undocumentedmatlab.com/blog/simulink-data-dictionary/feed 13
export_fighttps://undocumentedmatlab.com/blog/export_fig https://undocumentedmatlab.com/blog/export_fig#comments Wed, 21 Jan 2015 18:00:02 +0000 http://undocumentedmatlab.com/?p=5470
 
Related posts:
  1. Introduction to UDD UDD classes underlie many of Matlab's handle-graphics objects and functionality. This article introduces these classes....
  2. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
  3. 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...
  4. Hierarchical Systems with UDD UDD objects can be grouped in structured hierarchies - this article explains how...
 
]]>
I would like to introduce guest blogger Oliver Woodford. For the past several years Oliver has been a top contributor on the Matlab File Exchange, and several of his utilities have earned the prestigious distinction as “Pick of the Week”. This is no easy feat in a File Exchange that hosts ~23K utilities at latest count. For the past few years, excluding short spans of time, Oliver’s export_fig was the File Exchange’s most downloaded utility, by a wide margin. export_fig has improved the output quality of figures for so many numerous Matlab users that it is hard to imagine a Matlab File Exchange without it. Today, Oliver describes the basic technical mechanisms underlying export_fig.

Yair has very kindly agreed to take over maintenance of export_fig. For his benefit, and anyone else’s interest, I will briefly describe the layout and functionality of the toolbox.

Before starting, I always recommend that new users read the README file, to get a better understanding of the available options, how the functions perform, how to do certain frequently-asked things, and what problems still remain. The following excerpt comes from the README file (please do read the entire file):

If you’ve ever wondered what’s going on in the icon on the export_fig download page (reproduced below), then this explanation is for you: The icon is designed to demonstrate as many of export_fig‘s features as possible. Given a figure containing a translucent mesh (top right), export_fig can export to pdf (bottom center), which allows the figure to be zoomed in without losing quality (because it’s a vector graphic), but isn’t able to reproduce the translucency, and also, depending on the viewer, creates small gaps between the patches, which are seen here as thin white lines. By contrast, when exporting to png (top left), translucency is preserved (see how the graphic below shows through), the figure is anti-aliased, but zooming-in does not reveal more detail.

export_fig demo usage (click for details)

export_fig demo usage (click for details)


Goals of export_fig

  1. Publication quality

    I wrote export_fig to produce nice looking figures for my PhD thesis and journal papers. The two standard MATLAB functions for exporting figures are saveas and print. Unfortunately, the quality of their default outputs just wasn’t good enough. For example, images in PDF outputs would be heavily compressed and I wanted control over image quality.

    eps2pdf (which is part of the export_fig package) takes a quality setting as input, and converts this into suitable settings for ghostscript to convert the EPS file to a PDF, allowing users to get much higher fidelity output. In addition, ghostscript also crops the figure border to the EPS bounding box, and embeds fonts in the PDF. This last feature is obligatory for some publications, and export_fig is sometimes recommended by conferences or journals for this reason. Control of JPEG quality is achieved by passing the quality option to imwrite in export_fig.m.

    In export_fig.m, I also added anti-aliasing for raster outputs (by exporting at a higher resolution and downsizing), and alpha-matting (by exporting with both black and white backgrounds to compute transparency) for PNG outputs. The alpha-matting feature allows textured backgrounds to show through the exported figure, which can be useful for presentation slides. Here is an image that demonstrates such alpha-matting:

    Transparency alpha-matting

    Transparency alpha-matting

  2. WYSIWYG (what you see is what you get)

    Another issue with saveas and print is that, by default, they do not reproduce a figure exactly as it appears on screen. The dimensions change, the aspect ratio changes, the amount of whitespace changes, the background color changes, the axes ticks change, line dash lengths change, the fonts change, etc. All these changes are generally-undesirable side-effects of those functions.

    export_fig avoids these changes to the figure, ensuring that it gets exported as faithfully as possible to the on screen visualization. export_fig uses print under the hood, but changes various figure and axes settings to get the desired result. For example, in export_fig.m I call set(fig,'InvertHardcopy','off'), which ensures that the background color doesn’t change. I also set the axes Limits and Tick modes to 'manual', to ensure that axes don’t change. Similarly, in print2eps.m, I call set(fig, 'PaperPositionMode','auto', 'PaperOrientation','portrait') to ensure that the figure dimensions don’t change for vector outputs.

    Two of the changes, line dash lengths and fonts, are caused by the Painters renderer, and so they only occur in vector output. The only way to fix these issues was to edit the EPS file that print generates: fix_lines.m changes the definition of dash lengths in the EPS file, so that the dash lengths depend on the line widths. Likewise, print2eps.m changes unsupported fonts in the figure to supported ones, then reinserts the unsupported font into the EPS. Unfortunately this doesn’t work so well when the two fonts have different character widths.

    In addition to these features, the MATLAB rendering pipeline (in both HG1 and HG2 versions) is full of bugs. Many lines of code in export_fig are dedicated to circumventing these undocumented bugs. For example, lines 249-273 of today’s export_fig.m:

    % MATLAB "feature": black colorbar axes can change to white and vice versa!
    hCB = findobj(fig, 'Type', 'axes', 'Tag', 'Colorbar');
    if isempty(hCB)
        yCol = [];
        xCol = [];
    else
        yCol = get(hCB, 'YColor');
        xCol = get(hCB, 'XColor');
        if iscell(yCol)
            yCol = cell2mat(yCol);
            xCol = cell2mat(xCol);
        end
        yCol = sum(yCol, 2);
        xCol = sum(xCol, 2);
    end
     
    % MATLAB "feature": apparently figure size can change when changing colour in -nodisplay mode
    pos = get(fig, 'Position');
     
    % Set the background colour to black, and set size in case it was changed internally
    tcol = get(fig, 'Color');
    set(fig, 'Color', 'k', 'Position', pos);
     
    % Correct the colorbar axes colours
    set(hCB(yCol==0), 'YColor', [0 0 0]);
    set(hCB(xCol==0), 'XColor', [0 0 0]);

    Similarly, lines 143-160 of today’s print2eps.m:

    % MATLAB bug fix - black and white text can come out inverted sometimes
    % Find the white and black text
    black_text_handles = findobj(fig, 'Type', 'text', 'Color', [0 0 0]);
    white_text_handles = findobj(fig, 'Type', 'text', 'Color', [1 1 1]);
     
    % Set the font colors slightly off their correct values
    set(black_text_handles, 'Color', [0 0 0] + eps);
    set(white_text_handles, 'Color', [1 1 1] - eps);
     
    % MATLAB bug fix - white lines can come out funny sometimes
    % Find the white lines
    white_line_handles = findobj(fig, 'Type', 'line', 'Color', [1 1 1]);
     
    % Set the line color slightly off white
    set(white_line_handles, 'Color', [1 1 1] - 0.00001);
     
    % Print to eps file
    print(fig, options{:}, name);
     
    % Reset the font and line colors
    set(black_text_handles, 'Color', [0 0 0]);
    set(white_text_handles, 'Color', [1 1 1]);
    set(white_line_handles, 'Color', [1 1 1]);

Design philosophy

The export_fig toolbox is just a collection of functions. I put code into a separate function when either:

  1. One might want to use that functionality on its own, or
  2. That functionality is required by two or more other functions.

Subfunctions are used for code called multiple times in only one file, or where it improves legibility of the code.

The easiest way to understand the structure of the export_fig toolbox is to visualize the tree of function dependencies within the toolbox:

export_fig overview (click for details)

export_fig overview (click for details)

I’ll now describe what each function does in a bit more detail:

  1. export_fig

    This is the main function in the toolbox. It allows exporting a figure to several different file formats at once. It parses the input options. If only a subset of axes are being exported then it handles the transfer of these to a new figure (which gets destroyed at the end). It makes calls to print2array() for raster outputs, and print2eps() for vector outputs. For raster outputs, it also does the downsampling if anti-aliasing is enabled, and alphamatte computation if transparency is enabled. For vector outputs, it also does the conversion from eps to pdf, and also pdf back to eps. The reason for this last conversion is that the pdf is cropped, compressed and has the fonts embedded, and eps outputs should get this too (though I don’t think the font embedding remains).

  2. print2array

    This function rasterizes the figure. If the painters algorithm is specified then it calls print2eps(), then rasterizes the resulting EPS file using ghostscript. If another renderer is specified then this function just calls print() to output a bitmap. Finally, borders are cropped, if requested.

  3. print2eps

    This function calls print() to generate an EPS file, then makes several fixes to the EPS file, including making dash lengths commensurate with line width (old graphics system (HG1) only, i.e. R2014a or earlier), and substituting back in unsupported fonts.

  4. crop_borders

    Crops away any margin space surrounding the image(s): Given an image or stack of images (stacked along the 4th dimension), and a background color, crop_borders() computes the number of rows at the top and bottom and number of columns on the left and the right of the image(s) that are entirely the background color, and removes these rows and columns.

  5. ghostscript

    This function looks for a Ghostscript executable. or asks the user to specify its location. It then stores the path, or simply loads the path if one is already stored. It then calls the Ghostscript executable with the specified arguments.

  6. fix_lines

    This function makes dash lengths commensurate with line width, and converts grid lines from dashes to circular dots, in EPS files generated by MATLAB using HG1 (R2014a or earlier). fix_lines is also available as a separate File Exchange utility (selected for Pick-of–the-Week, just like export_fig). This function is no longer required in HG2 (R2014b or newer) – see below.

  7. read_write_entire_textfile

    Does what it says, reading or writing and entire text file from/to disk to/from memory, but handles errors gracefully, not leaving files open.

  8. eps2pdf

    This function converts an EPS file into a PDF file using Ghostscript.

  9. pdf2eps

    This function converts a PDF file into an EPS file using pdftops, from the Xpdf package.

  10. pdftops

    Does exactly the same thing as the ghostscript function, but for the pdftops executable instead.

  11. user_string

    This stores or loads user-specific strings in text files. This allows user-specific values to propagate across different versions of MATLAB, whilst avoiding these values being stored in version controlled code.

  12. copyfig

    This function simply creates a copy of a figure, like the built-in copyobj(). However, because the latter has some bugs, this function, which saves the figure to disk then opens it again, is required. Indeed, much of the code within the toolbox is simply circumventing bugs in MATLAB functions.

  13. isolate_axes

    This function removes unwanted axes from a figure. The approach to exporting a subset of axes is to copy the figure then remove the unwanted axes. Again, this is to circumvent bugs in the builtin function copyobj().

  14. using_hg2

    This function provides a robust way of checking if HG2 is in use (HG1 is the default in R2014a or older; HG2 is the default in R2014b or newer).

    In HG2, the entire rendering pipeline has changed. While most of the features remain the same, the bugs have completely changed. For example, dash lengths in HG2 vector output are now sensible, so fix_lines is not required. However, in R2014b at least, patch-based graphics generate bloated EPS files, and line widths cannot go below 0.75pt. Finally, an obvious change for raster output is that it is smoothed by default, so anti-aliasing is not required; the default settings in the parse_args() function within export_fig.m reflect this.

  15. append_pdfs

    export_fig does have a -append option, but this gets slower the larger the appended file becomes. A quicker way of generating a multipage PDF from several figures is to export them all to separate PDFs, then use this function to combine them into one in a single go. Also available as a separate File Exchange utility.

  16. im2gif

    This function converts a stack of images, or a multi-image TIFF file, to an animated GIF. export_fig can generate multi-image TIFFs using the -append option, making generating animated GIFs straightforward. Also available as a separate File Exchange utility.

And that’s it! All the functions have help text describing their input and output arguments.

Editorial notes

After several year of creating, improving and maintaining export_fig, Oliver is unfortunately no longer able to maintain this utility. As Oliver mentioned above, I (Yair) have volunteered to try to step into his shoes and maintain it. As Oliver’s detailed description (which barely scratches the surface) shows, this is certainly not a trivial utility. It will take me some time to get up to speed with all the internal technical details, so please be patient…

Readers interested in high-fidelity export might also consider using my ScreenCapture utility. Unlike export_fig, which uses Matlab’s builtin print function to generate (and fix) the output, ScreenCapture uses the standard java.awt.Robot.createScreenCapture() to take an actual screen-capture of the requested figure, axes or window area and then saves this to file/clipboard or sends it to the printer. In a sense, the export_fig and ScreenCapture utilities nicely complement each other.

]]>
https://undocumentedmatlab.com/blog/export_fig/feed 20
Transparency in uicontrolshttps://undocumentedmatlab.com/blog/transparency-in-uicontrols https://undocumentedmatlab.com/blog/transparency-in-uicontrols#comments Wed, 10 Dec 2014 18:00:34 +0000 http://undocumentedmatlab.com/?p=5302
 
Related posts:
  1. HG2 update HG2 appears to be nearing release. It is now a stable mature system. ...
  2. Graphic sizing in Matlab R2015b Matlab release R2015b's new "DPI-aware" nature broke some important functionality. Here's what can be done... ...
  3. Spicing up Matlab uicontrol tooltips Matlab uicontrol tooltips can be spiced-up using HTML and CSS, including fonts, colors, tables and images...
  4. Multi-line uitable column headers Matlab uitables can present long column headers in multiple lines, for improved readability. ...
 
]]>
I would like to welcome back guest blogger Robert Cumming, an independent UK contractor who developed a commercial class-based Matlab GUI framework. Today, Robert will highlight how he customized the use of uicontrol CData property.

Before detailing how I used this feature I will start with a basic example. A number of times (see example1, example2), users have asked is it possible to set the background of uicontrols to be transparent?

There are a number of reasons why we might want to do this. For example, we might wish to display a clickable image, and don’t want its background (which is typically white) to be displayed. To place on image on a uicontrol we use its CData property, which according to the official Matlab documentation must be a 3-D array of truecolor RGB values.

Let’s start with a simple example:

uicontrol with white bgcolor

uicontrol with white bgcolor

f = figure;
img = imread('Matlab_Logo.png');
s = size(img);
pb = uicontrol('Style','pushbutton', 'Position',[10 10 s(2) s(1)], 'CData',img, ...
               'Callback',@(a,b)disp('push button'), 'BackgroundColor','green');

The code above produces the figure on the right; when we click on the image, the pushbutton callback is executed.

However the background of the button is white. This is because the image is MxNx3 rectangle the size of the button.

We can set the white portion of the image to be transparent so that it will show the background color of the pushbutton (in our example, ‘green’).

First, we read the image and convert it to a 2D double array that ranges from 0 to 1 (the original image was RGB uint8, 0 to 255). Then find the index for each RGB where the value is 1 (white):

img = imread('Matlab_Logo.png');
img = double(img)/255;
index1 = img(:,:,1) == 1;
index2 = img(:,:,2) == 1;
index3 = img(:,:,3) == 1;
uicontrol with transparent bgcolor

uicontrol with transparent bgcolor

The color (in this example) that we want to make transparent is where all RGB is 1, so calculate a logical index where this is true and update the img variable:

indexWhite = index1+index2+index3==3;
for idx = 1 : 3
   rgb = img(:,:,idx);     % extract part of the image
   rgb(indexWhite) = NaN;  % set the white portion of the image to NaN
   img(:,:,idx) = rgb;     % substitute the update values
end
set(pb, 'CData', img)     % Update the CData variable

Updating the CData we get the image with the green background. We could set the Color of the figure to be green, to match the uicontrol’s background color:

set(f, 'Color', get(pb,'BackgroundColor'))

Transparent background

As mentioned here, we can link the CData to a screenshot image of the parent figure.

When we combine the two methods above, we get the effect of the uicontrol background being transparent (the smaller logo is a button that can be clicked):

uicontrol with transparent background (optical illusion)

uicontrol with transparent background (optical illusion)

f = figure(); % create a figure with an axes on it
ax = axes('Units','pixels', 'Position',[0 0 560 420], 'XTick',[], 'YTick',[], ...
          'Nextplot','add', 'YDir','reverse');
 
% read the big logo image - background of the figure
bigImage = imread('Matlab_LogoBig.png');
image(bigImage, 'parent', ax);  % Display the image in the axes
 
% read a smaller image - background of button
img = imread('Matlab_Logo.png');
s = size(img);
pos = [10 10 s(2) s(1)];  %Position of the button
 
% Extract the portion of the image where the button will be.
F = getframe(ax,pos);  % take a screenshot of the parent figure
pb = uicontrol('Style','pushbutton', 'Units','pixels', 'Position',pos, ...
               'Callback',@(a,b)disp('push button'));
 
% as before - calculate where the button image is white.
img = double(img)/255;
index1 = img(:,:,1) == 1;
index2 = img(:,:,2) == 1;
index3 = img(:,:,3) == 1;
indexWhite = index1+index2+index3==3;
 
% for each pixel, replace the white portion with the parent image data
for idx = 1 : 3
   rgb = 1-img(:,:,idx);                   % To make the picture quirky change the RGB
   pImage = double(F.cdata(:,:,idx))/255;  % extract part of the image
   rgb(indexWhite) = pImage(indexWhite);   % set the white portion of the image to the parent
   img(:,:,idx) = rgb;                     % substitute the update values
end
 
% Update the push button image
set(pb, 'CData', img)

Customizing checkboxes

I have shown how to manipulate the CData of a button. Unfortunately, not all uicontrols have a CData property — the documentation states that pushbuttons and toggle buttons are the only uicontrols that are fully supported. It also mentions that you can use it in radiobuttons and checkboxes, which brings me to how I used it in my application: I use this feature on a checkbox – to use it properly we need to ensure that the size of the image we put in CData is 16x16x3. In this case we set a transparent color by setting pixel RGB values to NaN:

uicontrol with transparent bgcolor

uicontrol with transparent bgcolor

f = figure('Color','red');
smiley = imread('smiley.png');
smiley = double(smiley)/255;
index1 = smiley(:,:,1) == 1;
index2 = smiley(:,:,2) == 1;
index3 = smiley(:,:,3) == 1;
indexWhite = index1+index2+index3==3;
 
% Create a first smiley which has the white background.
uicontrol('Style','checkbox', 'Position',[25 50 16, 16], 'CData',smiley, ...
          'Callback',@(a,b)disp('-1 smiley'));
 
% For each pixel, replace the white portion with the parent image data
for idx = 1 : 3
   rgb = smiley(:,:,idx);  % To make the picture quirky change the RGB
   rgb(indexWhite) = NaN;
   smiley(:,:,idx) = rgb;  % substitute the update values.
end
 
% Create a second smiley which has the transparent background.
uicontrol('Style','checkbox', 'Position',[25 25 16, 16], 'CData',smiley, ...
          'Callback',@(a,b)disp('+1 smiley'), 'BackgroundColor','red');

The upper smiley is the original image; the lower smiley has its white pixels set to NaN, and the background colors of the control and the figure set to equal. The checkbox has no text is displayed, the user just clicks on the smiley to invoke the callback.

Note: This trick works in R2014b but I have deliberately used old style set and get commands for compatibility with older versions of Matlab. I have used this in all versions from R2008a onwards, and I suspect it probably works in older versions as well.

I used this feature several times in my Matlab GUI Toolbox. One of the uses was to create a pin for locking a dynamic panel in position: The panel is by default hidden; when the user hovers the mouse near the edge, the dynamic panel appears after some predefined time (2 seconds). A checkbox with a manipulated CData masquerades as a pin for locking the panel in position. When the panel is pinned, the CData changes accordingly:

transparent uicontrol usage example
transparent uicontrol usage example

Conclusions

1. The CData property of a uicontrol can be set to NaN to imitate transparent behavior.
2. By linking this with the parent CData we can super-impose an image on top of another image.
3. We can customize other uicontrols using the method to turn checkboxes (for example) into clickable images.

Have you used this feature? If so please share in a comment below.

Editor’s note: I have shown another alternative for displaying clickable transparent images in my article on displaying animated/transparent GIFs. Readers might also find interest in the related article on transparent uipanels. Next week I plan to show how MathWorkers Ben Tordoff and David Sampson coerced a simple checkbox uicontrol to have a radically different appearance, as flex-panel dividers in their GUI Layout Toolbox, similarly to what Robert explained today. Stay tuned!  – Yair

]]>
https://undocumentedmatlab.com/blog/transparency-in-uicontrols/feed 5
Inter-Matlab data transfer with memcachedhttps://undocumentedmatlab.com/blog/inter-matlab-data-transfer-with-memcached https://undocumentedmatlab.com/blog/inter-matlab-data-transfer-with-memcached#comments Wed, 27 Aug 2014 12:26:57 +0000 http://undocumentedmatlab.com/?p=4969
 
Related posts:
  1. JGit-Matlab integration JGit source-control integration package can easily be integrated in Matlab. ...
  2. Solving a MATLAB bug by subclassing Matlab's Image Processing Toolbox's impoint function contains an annoying bug that can be fixed using some undocumented properties....
  3. Controlling callback re-entrancy Callback reentrancy is a major problem for frequently-fired events. Luckily, it can easily be solved....
  4. Using Groovy in Matlab Groovy code can seamlessly be run from within Matlab. ...
 
]]>
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.

]]>
https://undocumentedmatlab.com/blog/inter-matlab-data-transfer-with-memcached/feed 2
Using pure Java GUI in deployed Matlab appshttps://undocumentedmatlab.com/blog/using-pure-java-gui-in-deployed-matlab-apps https://undocumentedmatlab.com/blog/using-pure-java-gui-in-deployed-matlab-apps#comments Thu, 10 Jul 2014 16:21:09 +0000 http://undocumentedmatlab.com/?p=4909
 
Related posts:
  1. Matlab and the Event Dispatch Thread (EDT) The Java Swing Event Dispatch Thread (EDT) is very important for Matlab GUI timings. This article explains the potential pitfalls and their avoidance using undocumented Matlab functionality....
  2. Fixing a Java focus problem Java components added to Matlab GUIs do not participate in the standard focus cycle - this article explains how to fix this problem....
  3. Blurred Matlab figure window Matlab figure windows can be blurred using a semi-transparent overlaid window - this article explains how...
  4. Customizing menu items part 3 Matlab menu items can easily display custom icons, using just a tiny bit of Java magic powder. ...
 
]]>
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 https://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.

]]>
https://undocumentedmatlab.com/blog/using-pure-java-gui-in-deployed-matlab-apps/feed 20
Plotly graphs in IPython Notebookhttps://undocumentedmatlab.com/blog/plotly-graphs-in-ipython-notebook https://undocumentedmatlab.com/blog/plotly-graphs-in-ipython-notebook#comments Wed, 14 May 2014 18:00:22 +0000 http://undocumentedmatlab.com/?p=4797
 
Related posts:
  1. Plotly graphs Plotly charts can be created and customized in Matlab. ...
  2. GUI automation utilities This article explains a couple of Matlab utilities that use Java's Robot class to programmatically control mouse and keyboard actions...
  3. Controlling callback re-entrancy Callback reentrancy is a major problem for frequently-fired events. Luckily, it can easily be solved....
  4. Transparency in uicontrols Matlab uicontrols' CData property can be customized to provide background transparency....
 
]]>
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.

]]>
https://undocumentedmatlab.com/blog/plotly-graphs-in-ipython-notebook/feed 1
uicontextmenu performancehttps://undocumentedmatlab.com/blog/uicontextmenu-performance https://undocumentedmatlab.com/blog/uicontextmenu-performance#comments Wed, 02 Apr 2014 18:00:29 +0000 http://undocumentedmatlab.com/?p=4751
 
Related posts:
  1. Plot LimInclude properties The plot objects' XLimInclude, YLimInclude, ZLimInclude, ALimInclude and CLimInclude properties are an important feature, that has both functional and performance implications....
  2. Accessing plot brushed data Plot data brushing can be accessed programmatically using very simple pure-Matlab code...
  3. Performance: accessing handle properties Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
  4. Customizing axes part 2 Matlab HG2 axes can be customized in many different ways. This article explains some of the undocumented aspects. ...
 
]]>
I would like to introduce guest blogger Robert Cumming, an independent contractor based in the UK who has recently worked on certification of the newest advanced civil aircraft. Today Robert will discuss the performance of uicontextmenus in interactive GUIs, which were used extensively in flight test analysis.

Have you ever noticed that a GUI slows down over time? I was responsible for designing a highly complex interactive GUI, which plotted flight test data for engineers and designers to analyze data for comparison with pre-flight predictions. This involved extensive plotting of data (pressure, forces/moments, anemometry, actuator settings etc….), where individual data points were required to have specific/customizable uicontextmenus.

Matlab’s documentation on uicontextmenus discusses adding them to plots, but makes no mention of the cleaning up afterwards.

Let’s start with some GUI basics. First we create a figure with a simple axes and a line:

x = [-10:0.2:10];
y = x.^2;
h = figure;
ax = axes ( 'parent',h );
hplot = plot ( ax, x, y );

Adding a uicontextmenu to the plot creates extra objects:

uic = uicontextmenu;
uimenu ( uic, 'Label','Menu A.1' );
set ( hplot, 'uicontextmenu',uic );
fprintf ( 'Figure (h) has %i objects\n', length ( findobj ( h ) ) );

In this instance there are 5 objects, the individual menu and uicontextmenu have created an additional 2 objects. All of this is quite basic as you would expect.

Basic plot with a custom context menu

Basic plot with a custom context menu


We now clear the plot using cla and draw a new line with its own new uicontextmenu. Note that we don’t save the plot handle this time:

cla ( ax );
uic = uicontextmenu;
uimenu ( uic, 'Label','Menu B.1' );
plot ( ax, x, -y , 'uicontextmenu',uic );
fprintf ( 'Figure (h) has %i objects\n', length ( findobj ( h ) ) );

Another basic plot with a new context menu

Another basic plot with a new context menu

This time the fprintf line tells us that the figure has 7 objects. This may not have been expected, as the first plot was cleared and the original context menu is no longer accessible (cla removed the plot and the line object hplot).

Let’s check these object handles:

>> ishandle ( findobj( h ) )'
ans =
     1     1     1     1     1     1     1     1     1     1     1     1     1

We see that all the objects are valid handles. At first this may perhaps appear confusing: after all, the plot with “Menu A.1” was deleted. Let’s check this:

>> ishandle ( hplot )
ans =
     0
 
>> get(hplot)
Error using handle.handle/get
Invalid or deleted object.

So it appears that although the plot line was indeed deleted, its associated context menu was not. The reason for this is that the context menu is created as a child of the figure window, not the plot. We are simply using the plot line’s UIContextMenu property to allow the user to obtain access to it and its associated menus.

Once we understand this we can do two things:

  1. Use the same uicontextmenu for each plot
  2. Built individual uicontextmenus for each plot, but remember to clean up afterwards

Is this really such a big issue?

You may be wondering how big a problem is this creation of extra objects. The answer is that for simple cases like this it is really not a big issue. But let’s consider a more realistic case where we also assign callbacks to the menus. First we will create a figure with an axes, for plotting on and a uicontrol edit for displaying a message:

function uicontextExample
   h.main = figure;
   h.ax = axes ( 'parent',h.main, 'NextPlot','add', 'position',[0.1 0.2 0.8 0.7] );
   h.msg = uicontrol ( 'style','edit', 'units','normalized', 'position',[0.08 0.01 0.65 0.1], 'backgroundcolor','white' );
   uicontrol ( 'style','pushbutton', 'units','normalized', 'position',[0.75 0.01 0.2 0.1], 'Callback',{@RedrawX20 h}, 'string','re-draw x20' );
   redraw ( [], [], h )  % see below
end

The callback redraw (shown below) draws a simple curve and assigns individual uicontextmenus to each individual item in the plot. Each uicontextmenu has 12 menu items:

function redraw ( obj, event, h, varargin )
   cla(h.ax);
   start = tic;
   x = -50:50;
   y = x.^2;
   for ii = 1 : length(x)
      uim = uicontextmenu ( 'parent',h.main );
      for jj = 1 : 10
         menuLabel = sprintf ( 'Menu %i.%i', ii, jj );
         uimenu ( 'parent',uim, 'Label',menuLabel, 'Callback',{@redraw h} )
      end
      xStr = sprintf ( 'X = %f', x(ii) );
      yStr = sprintf ( 'Y = %f', y(ii) );
      uimenu ( 'parent',uim, 'Label',xStr, 'Callback',{@redraw h} )
      uimenu ( 'parent',uim, 'Label',yStr, 'Callback',{@redraw h} )
      plot ( h.ax, x(ii), y(ii), 'rs', 'uicontextmenu',uim );
   end
   objs = findobj ( h.main );
   s = sprintf ( 'figure contains %i objects - drawn in %3.2f seconds', length(objs), toc(start) );
   set ( h.msg, 'string',s );
   fprintf('%s\n',s)
end

To help demonstrate the slow-down in speed, the pushbutton uicontrol will redraw the plot 20 times, and show the results from the profiler:

function RedrawX20 ( obj, event, h )
   profile on
   set ( obj, 'enable','off' )
   for ii = 1 : 20
      redraw ( [], [], h );
      drawnow();
   end
   set ( obj, 'enable','on' )
   profile viewer
end

The first time we run this, on a reasonable laptop it takes 0.24 seconds to draw the figure with all the menus:

Multiple context menus assigned to individual data points

Multiple context menus assigned to individual data points

When we press the <re-draw x20> button we get:

figure contains 2731 objects - drawn in 0.28 seconds
figure contains 4044 objects - drawn in 0.28 seconds
figure contains 5357 objects - drawn in 0.28 seconds
figure contains 6670 objects - drawn in 0.30 seconds
figure contains 7983 objects - drawn in 0.32 seconds
figure contains 9296 objects - drawn in 0.30 seconds
figure contains 10609 objects - drawn in 0.31 seconds
figure contains 11922 objects - drawn in 0.30 seconds
figure contains 13235 objects - drawn in 0.32 seconds
figure contains 14548 objects - drawn in 0.30 seconds
figure contains 15861 objects - drawn in 0.31 seconds
figure contains 17174 objects - drawn in 0.31 seconds
figure contains 18487 objects - drawn in 0.32 seconds
figure contains 19800 objects - drawn in 0.33 seconds
figure contains 21113 objects - drawn in 0.32 seconds
figure contains 22426 objects - drawn in 0.33 seconds
figure contains 23739 objects - drawn in 0.35 seconds
figure contains 25052 objects - drawn in 0.34 seconds
figure contains 26365 objects - drawn in 0.35 seconds
figure contains 27678 objects - drawn in 0.35 seconds

The run time shows significant degradation, and we have many left-over objects. The profiler output confirms where the time is being spent:

Profiling results - context menu creation is an evident hotspot

Profiling results - context menu creation is an evident hotspot

As expected the menus creation takes most of the time. Note that the timing that you will get on your own computer for this example may vary and the slowdown may be less noticeable.

Let’s extend the example to include extra input arguments in the callback (in this example they are not used – but in the industrial example extra input arguments are very possible, and were required by the customer):

for ii=1:length(x)
   uim = uicontextmenu ( 'parent',h.main );
   for jj = 1 : 10
      menuLabel = sprintf ( 'Menu %i.%i', ii, jj );
      uimenu ( 'parent',uim, 'Label',menuLabel, 'Callback',{@redraw h 1 0 1} )
   end
   xStr = sprintf ( 'X = %f', x(ii) );
   yStr = sprintf ( 'Y = %f', y(ii) );
   uimenu ( 'parent',uim, 'Label',xStr, 'Callback',{@redraw h 1 0 1} )
   uimenu ( 'parent',uim, 'Label',yStr, 'Callback',{@redraw h 1 0 1} )
   plot ( h.ax, x(ii), y(ii), 'rs', 'uicontextmenu',uim );
end

Re-running the code and pressing <re-draw x20> we get:

figure contains 1418 objects - drawn in 0.29 seconds
figure contains 2731 objects - drawn in 0.37 seconds
figure contains 4044 objects - drawn in 0.48 seconds
figure contains 5357 objects - drawn in 0.65 seconds
...
figure contains 23739 objects - drawn in 4.99 seconds
figure contains 25052 objects - drawn in 5.34 seconds
figure contains 26365 objects - drawn in 5.88 seconds
figure contains 27678 objects - drawn in 6.22 seconds

Note that the 6.22 seconds is just the time that it took the last individual redraw, not the total time to draw 20 times (which was just over a minute). The profiler is again used to confirm that the vast majority of the time (57 seconds) was spent in the uimenu calls, mostly on line #23. In comparison, all other lines together took just 4 seconds to run.

The simple act of adding extra inputs to the callback has completely transformed the speed of our code.

How real is this example?
In code written for a customer, the context menu had a variety of sub menus (dependent on the parameter being plotted – from 5 to ~20), and they each had multiple parameters passed into the callbacks. Over a relatively short period of time the user would cycle through a lot of data and the number of uicontextmenus being created was surprisingly large. For example, users would easily look at 100 individual sensors recorded at 10Hz for 2 minutes (100*10*60*2). If all sensors and points are plotted individually that would be 120,000 uicontextmenus!

So how do we resolve this?

The problem is addressed by simply deleting the context menu handles once they are no longer needed. This can be done by adding a delete command after cla at the top of the redraw function, in order to remove the redundant uicontextmenus:

function redraw ( obj, event, h, varargin )
   cla(h.ax);
   delete ( findobj ( h.main, 'type','uicontextmenu' ) )   set ( h.msg, 'string','redrawing' );
   start = tic;
   ...

If we now click <redraw x20> we see that the number of objects and the time to create them remain its essentially the same as the first call: 1418 objects and 0.28 seconds:

figure contains 1418 objects - drawn in 0.28 seconds
figure contains 1418 objects - drawn in 0.30 seconds
figure contains 1418 objects - drawn in 0.33 seconds
figure contains 1418 objects - drawn in 0.29 seconds
figure contains 1418 objects - drawn in 0.29 seconds
...

Advanced users could use handle listeners to attached a callback such that when a plot element is deleted, so too are its associated context menus.

Conclusions

Things to consider with uicontextmenus:

  1. Always delete uicontextmenus that you have finished with.
  2. If you have multiple uicontextmenus you will want to only delete the ones associated with the axes being cleared – otherwise you will delete more than you want to.
  3. Try to reduce the number of input arguments to your callbacks, group into a structure or cell array.
  4. Re-use uicontextmenus where possible.

Have you had similar experiences? Or other issues where GUI slow down over time? If so, please leave a comment below.

]]>
https://undocumentedmatlab.com/blog/uicontextmenu-performance/feed 5