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

Customizing axes part 3

$
0
0

In the past two weeks I explained how HG2 (in R2014b) enables us to customize the axes rulers, baselines, box and grid-lines in ways that were previously impossible in HG1 (R2014a or earlier). Today I will describe other useful undocumented customizations of the HG2 axes:

Backdrop

The axes’ Backdrop (a matlab.graphics.axis.decorator.Backdrop object) controls the background color of the axes’ content area. This is normally white, but can be set to any color, including translucency:

% Create the plot
x = -10:0.1:10;
y = 1e7*sin(x)./x; 
hLine = plot(x,y);
hAxes = gca;
box('off');
 
% Set a light-yellow backdrop
hAxes.Backdrop.FaceColor = [1, 1, 0, 0.4];

HG2 axes Backdrop

HG2 axes Backdrop

By default, Backdrop spans the entire (rectangular) axes content area. But we can customize its vertex points using the Face.VertexData property, which accepts an array of 3xN singles:

HG2 axes Backdrop with custom vertex points

HG2 axes Backdrop with custom vertex points

% Note: VertexData is specified in normalized (0-1) units, not data units
hAxes.Backdrop.Face.VertexData = single([0,1,0.8,0; 0,0.43,0.75,1; 0,0,0,0]);  % default: [0,1,1,0; 0,0,1,1; 0,0,0,0]
 
>> hAxes.Backdrop.Face.get
             AmbientStrength: 0.3
             BackFaceCulling: 'none'
                ColorBinding: 'object'
                   ColorData: [4x1 uint8]
                   ColorType: 'truecoloralpha'
             DiffuseStrength: 0.6
            HandleVisibility: 'off'
                     HitTest: 'off'
                       Layer: 'back'
               NormalBinding: 'none'
                  NormalData: []
                      Parent: [1x1 Backdrop]
               PickableParts: 'all'
    SpecularColorReflectance: 1
            SpecularExponent: 10
            SpecularStrength: 0.9
                   StripData: []
                     Texture: []
            TwoSidedLighting: 'off'
                  VertexData: [3x4 single]
               VertexIndices: []
                     Visible: 'on'

The down side is that whenever we modify anything in the axes (or even get some axes property values), Face.VertexData is reset back to its default value of [0,1,1,0; 0,0,1,1; 0,0,0,0], so we need to either update it in a timer and/or in a property listener.

We can create a tint (gradient color) effect by setting the Face.ColorData property to match the vertex points and modifying Face.ColorBinding from the default ‘object’ to ‘interpolated’ (other alternative values are ‘discrete’ and ‘none’):

colorData = uint8([255, 150, 200, 100; ...  % instead of [255;255;0;102] = light-yellow
                   255, 100,  50, 200; ...
                     0,  50, 100, 150; ...
                   102, 150, 200,  50]);
set(hAxes.Backdrop.Face, 'ColorBinding','interpolated', 'ColorData',colorData);

HG2 axes Backdrop with custom vertex, tint

HG2 axes Backdrop with custom vertex, tint

The tint effect does not rely on the vertex – we can set a tinted background for the entire content area by modifying Face.ColorData without modifying the vertexes:

HG2 axes Backdrop with custom tint

HG2 axes Backdrop with custom tint

Of course, one could say that this is not much better than creating a patch that has the specified vertex points and colors. For example:

% Create a patch to replace the backdrop
cdata = [255, 150, 200, 100; ...
         255, 100,  50, 200; ...
           0,  50, 100, 150 ...
        ]' / 255;  % alpha values are not directly accepted by patch CData
vertexData = [0,1,0.8,0; 0,0.43,0.75,1];  % in normalized units
xdata = hAxes.XLim(1) + diff(hAxes.XLim)*vertexData(1,:);  % in data units
ydata = hAxes.YLim(1) + diff(hAxes.YLim)*vertexData(2,:);  % in data units
hPatch = patch(xdata, ydata, 'k', 'Parent',hAxes, 'EdgeColor','none', ...
               'FaceVertexCData',cdata, 'FaceColor','interp', ...
               'FaceVertexAlpha',[102;150;200;50]/255, 'FaceAlpha','interp');

This results in a gradient very similar to the BackDrop, although not exactly the same. Perhaps the color interpolation for BackDrop is different than for patches, or maybe I just made a mistake somewhere above…

Standard patch with custom tint

Standard patch with custom tint

I don’t have a good answer as to why MathWorks chose to add the BackDrop property to HG2 axes and what advantage it might have over a separate patch. If anyone has an idea, please post a comment below. We can be pretty sure that this was discussed at MathWorks, since Michelle Hirsch, who heads Matlab product development at MathWorks, posted a utility that implements a patch-based gradient backdrop back in 2010 and has recently rehosted it on GitHub:

Michelle Hirsch's patch-based gradient backdrop utility

Michelle Hirsch's patch-based gradient backdrop utility

SortMethod

SortMethod is a newly-supported axes property in R2014b. It is new only in the sense that it became documented: It has existed in its present form also in previous Matlab releases, as a hidden axes property (I’m not sure exactly from which release). This is yet another example of an undocumented Matlab functionality that existed for many years before MathWorks decided to make it official (other examples in R2014b are the set of uitab/uitabgroup functions).

SortMethod is important due to its impact on graphic rendering performance: By default, Matlab draws objects in a back-to-front order based on the current view. This means that objects (lines, patches etc.) which should appear “on top” of other objects are drawn last, overlapping the objects “beneath” them. Calculating the order of the objects, especially in complex plots having multiple overlapping segments, can take noticeable time. We can improve performance by telling the renderer to draw objects in the order of the Children property, which is typically the order in which the objects were created. This can be done by setting the axes’ SortMethod property to ‘childorder’ (default=’depth’). Since SortOrder existed in past Matlab releases as well, we can use this technique on the older MATLAB releases just as for R2014b or newer.

In a related matter, we should note that transparent/translucent patches and lines (having a 4th Color element (alpha) value between 0.0 and 1.0) are slower to render for much the same reasons. Reducing the number of transparent/translucent objects will improve graphics rendering performance. Note that specifying a 4th Color element is again an undocumented feature: Matlab officially only supports RGB triplets and named color strings, not RGBA quadruplets. I’ll discuss this aspect next week.

WarpToFill

WarpToFill (default=’on’) is a simple flag that controls whether or not the axes should fill its container (panel or figure), leaving minimal margins. We can consider this as another variant to the documented alternatives of the axis function:

surf(peaks);
set(gca,'WarpToFill','off');

HG2 axes WarpToFill on HG2 axes WarpToFill off

HG2 axes WarpToFill (on, off)

Note that WarpToFill is not new in R2014b – it has existed in its present form also in previous Matlab releases, as a hidden axes property. One would hope that it will finally become officially supported, as SortMethod above has.

Camera

The Camera object (matlab.graphics.axis.camera.Camera3D) controls the 3D camera/lighting of the axes. This is normally controlled via the 3D figure toolbar and related functions (view, camup, campos etc.). We can have better granularity by discretely customizing the internal hidden properties:

>> hAxes.Camera.get
               AspectRatio: 1
                  Children: []
      DepthCalculationHint: 'careful'
                 DepthSort: 'on'
          HandleVisibility: 'off'
                    Parent: [1x1 Axes]
        PlotBoxAspectRatio: [1 1 1]
    PlotBoxAspectRatioMode: 'auto'
                  Position: [-4.06571071756541 -5.45015005218426 4.83012701892219]
                Projection: 'orthographic'
                    Target: [0.5 0.5 0.5]
    TransparencyMethodHint: 'depthpeel'
                  UpVector: [0 0 1]
                 ViewAngle: 10.339584907202
                  Viewport: [1x1 matlab.graphics.general.UnitPosition]
                   Visible: 'on'
                WarpToFill: 'vertical'

This concludes my series on undocumented HG2 axes customizations (at least for now). Next week, I will describe undocumented HG2 plot-line customizations.

 
Related posts:
  1. Customizing axes part 2 Matlab HG2 axes can be customized in many different ways. This article explains some of the undocumented aspects. ...
  2. Customizing axes rulers HG2 axes can be customized in numerous useful ways. This article explains how to customize the rulers. ...
  3. Determining axes zoom state The information of whether or not an axes is zoomed or panned can easily be inferred from an internal undocumented object....
  4. Axes LooseInset property Matlab plot axes have an undocumented LooseInset property that sets empty margins around the axes, and can be set to provide a tighter fit of the axes to their surroundings....
 

Customizing axes part 4 – additional properties

$
0
0

In the past three weeks I explained how HG2 (in R2014b) enables us to customize the axes rulers, back-drop, baselines, box and grid-lines in ways that were previously impossible in HG1 (R2014a or earlier). Today I will conclude the mini-series on axes customizations by describing other useful undocumented customizations of the HG2 axes:

Camera

The Camera object (matlab.graphics.axis.camera.Camera3D) controls the 3D camera/lighting of the axes. Camera is a new hidden property of HG2 axes, that did not exist in earlier Matlab releases (HG1). This functionality is normally controlled via the 3D figure toolbar and related functions (view, camup, campos etc.). We can have better granularity by discretely customizing Camera‘s properties:

>> hAxes.Camera.get
               AspectRatio: 1
                  Children: []
      DepthCalculationHint: 'careful'
                 DepthSort: 'on'
          HandleVisibility: 'off'
                    Parent: [1x1 Axes]
        PlotBoxAspectRatio: [1 1 1]
    PlotBoxAspectRatioMode: 'auto'
                  Position: [-4.06571071756541 -5.45015005218426 4.83012701892219]
                Projection: 'orthographic'
                    Target: [0.5 0.5 0.5]
    TransparencyMethodHint: 'depthpeel'
                  UpVector: [0 0 1]
                 ViewAngle: 10.339584907202
                  Viewport: [1x1 matlab.graphics.general.UnitPosition]
                   Visible: 'on'
                WarpToFill: 'vertical'

SortMethod

SortMethod is a newly-supported axes property in R2014b. It is new only in the sense that it became documented: It has existed in its present form also in previous Matlab releases, as a hidden axes property (I’m not sure exactly from which release). This is yet another example of an undocumented Matlab functionality that existed for many years before MathWorks decided to make it official (other examples in R2014b are the set of uitab/uitabgroup functions).

SortMethod is important due to its impact on graphic rendering performance: By default, Matlab draws objects in a back-to-front order based on the current view. This means that objects (lines, patches etc.) which should appear “on top” of other objects are drawn last, overlapping the objects “beneath” them. Calculating the order of the objects, especially in complex plots having multiple overlapping segments, can take noticeable time. We can improve performance by telling the renderer to draw objects in the order of the Children property, which is typically the order in which the objects were created. This can be done by setting the axes’ SortMethod property to ‘childorder’ (default=’depth’). Since SortOrder existed in past Matlab releases as well, we can use this technique on the older MATLAB releases just as for R2014b or newer.

In a related matter, we should note that transparent/translucent patches and lines (having a 4th Color element (alpha) value between 0.0 and 1.0) are slower to render for much the same reasons. Reducing the number of transparent/translucent objects will improve graphics rendering performance. Note that specifying a 4th Color element is again an undocumented feature: Matlab officially only supports RGB triplets and named color strings, not RGBA quadruplets. I’ll discuss this aspect next week.

WarpToFill

WarpToFill (default=’on’) is a simple flag that controls whether or not the axes should fill its container (panel or figure), leaving minimal margins. We can consider this as another variant to the documented alternatives of the axis function:

surf(peaks);
set(gca,'WarpToFill','off');

HG2 axes WarpToFill on HG2 axes WarpToFill off

HG2 axes WarpToFill (on, off)

Note that WarpToFill is not new in R2014b – it has existed in its present form also in previous Matlab releases, as a hidden axes property. One would hope that it will finally become officially supported, as SortMethod above has.

Additional properties

Additional undocumented aspects of Matlab axes that I have reported over the years, including the LooseInset property and determining axes zoom state, still work in HG2 (R2014b). They might be removed someday, but hopefully they will take the opposite path that SortMethod did, of becoming fully supported.

On the other hand, some important undocumented HG1 axes properties have been removed: x_NormRenderTransform, x_ProjectionTransform, x_RenderOffset, x_RenderScale, x_RenderTransform, x_ViewPortTransform and x_ViewTransform could be used in HG1 axes to map between 3D and 2D data spaces. Some users have already complained about this. I have [still] not found a simple workaround for this, but I’m pretty sure that there is one. Maybe the hidden axes DataSpace property could be used for this, but I’m not sure how exactly.

This concludes my series on undocumented HG2 axes customizations (at least for now). Next week, I will describe undocumented HG2 plot-line customizations.

 
Related posts:
  1. Customizing axes part 2 Matlab HG2 axes can be customized in many different ways. This article explains some of the undocumented aspects. ...
  2. Customizing axes part 3 – Backdrop Matlab HG2 axes can be customized in many different ways. This article explains some of the undocumented aspects. ...
  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. Performance: accessing handle properties Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
 

Plot line transparency and color gradient

$
0
0

In the past few weeks, I discussed the new HG2 axes Backdrop and Baseline properties with their associated ability to specify the transparency level using a fourth (undocumented) element in their Color.

In other words, color in HG2 can still be specified as an RGB triplet (e.g., [1,0,0] to symbolize bright red), but also via a 4-element quadruplet RGBA, where the 4th element (Alpha) signifies the opacity level (0.0=fully transparent, 0.5=semi-transparent, 1.0=opaque). So, for example, [1, 0, 0, 0.3] means a 70%-transparent red.

This Alpha element is not documented anywhere as being acceptable, but appears to be supported almost universally in HG2 wherever a color element can be specified. In some rare cases (e.g., for patch objects) Matlab has separate Alpha properties that are fully documented, but in any case nowhere have I seen documented that we can directly set the alpha value in the color property, especially for objects (such as plot lines) that do not officially support transparency. If anyone finds a documented reference anywhere, please let me know – perhaps I simply missed it.

Here is a simple visualization:

xlim([1,5]);
hold('on');
h1a = plot(1:5,     11:15, '.-', 'LineWidth',10, 'DisplayName',' 0.5');
h1b = plot(1.5:5.5, 11:15, '.-', 'LineWidth',10, 'DisplayName',' 1.0', 'Color',h1a.Color);  % 100% opaque
h1a.Color(4) = 0.5;  % 50% transparent
h2a = plot(3:7,  15:-1:11, '.-r', 'LineWidth',8, 'DisplayName',' 0.3'); h2a.Color(4)=0.3;  % 70% transparent
h2b = plot(2:6,  15:-1:11, '.-r', 'LineWidth',8, 'DisplayName',' 0.7'); h2b.Color(4)=0.7;  % 30% transparent
h2c = plot(1:5,  15:-1:11, '.-r', 'LineWidth',8, 'DisplayName',' 1.0');  % 100% opaque = 0% transparent
legend('show','Location','west')

Transparent HG2 plot lines

Transparent HG2 plot lines

Now for the fun part: we can make color-transition (gradient) effects along the line, using its hidden Edge property:

>> h2b.Edge.get
          AlignVertexCenters: 'off'
             AmbientStrength: 0.3
                ColorBinding: 'object'
                   ColorData: [4x1 uint8]
                   ColorType: 'truecoloralpha'
             DiffuseStrength: 0.6
            HandleVisibility: 'off'
                     HitTest: 'off'
                       Layer: 'middle'
                   LineStyle: 'solid'
                   LineWidth: 8
               NormalBinding: 'none'
                  NormalData: []
                      Parent: [1x1 Line]
               PickableParts: 'visible'
    SpecularColorReflectance: 1
            SpecularExponent: 10
            SpecularStrength: 0.9
                   StripData: [1 6]
                     Texture: []
                  VertexData: [3x5 single]
               VertexIndices: []
                     Visible: 'on'
       WideLineRenderingHint: 'software'
 
>> h2b.Edge.ColorData  %[4x1 uint8]
ans =
  255
    0
    0
  179

The tricky part is to change the Edge.ColorBinding value from its default value of ‘object’ to ‘interpolated’ (there are also ‘discrete’ and ‘none’). Then we can modify Edge.ColorData from being a 4×1 array of uint8 (value of 255 corresponding to a color value of 1.0), to being a 4xN matrix, where N is the number of data points specified for the line, such that each data point along the line will get its own unique RGB or RGBA value. (the data values themselves are kept as a 3xN matrix of single values in Edge.VertexData).

So, for example, let’s modify the middle (30%-transparent) red line to something more colorful:

>> cd=uint8([255,200,250,50,0; 0,50,250,150,200; 0,0,0,100,150; 179,150,200,70,50])
cd =
  255  200  250   50    0
    0   50  250  150  200
    0    0    0  100  150
  179  150  200   70   50
 
>> set(h2b.Edge, 'ColorBinding','interpolated', 'ColorData',cd)

HG2 plot line color, transparency gradient

HG2 plot line color, transparency gradient

As you can see, we can interpolate not only the colors, but also the transparency along the line.

Note: We need to update all the relevant properties together, in a single set() update, otherwise we’d get warning messages about incompatibilities between the property values. For example:

>> h2b.Edge.ColorBinding = 'interpolated';
Warning: Error creating or updating LineStrip
 Error in value of property ColorData
 Array is wrong shape or size
(Type "warning off MATLAB:gui:array:InvalidArrayShape" to suppress this warning.)

Markers

Note how the markers are clearly seen in the transparent lines but not the opaque ones. This is because the markers have the same color as the lines in today’s example. Since the lines are wide, the markers are surrounded by pixels of the same color. Therefore, the markers are only visible when the surrounding pixels are less opaque (i.e., lighter).

As a related customization, we can control whether the markers appear “on top of” (in front of) the line or “beneath” it by updating the Edge.Layer property from ‘middle’ to ‘front’ (there is also ‘back’, but I guess you won’t typically use it). This is important for transparent lines, since it controls the brightness of the markers: “on top” (in front) they appear brighter. As far as I know, this cannot be set separately for each marker – they are all updated together.

Of course, we could always update the line’s fully-documented MarkerSize, MarkerFaceColor and MarkerEdgeColor properties, in addition to the undocumented customizations above.

Next week I will describe how we can customize plot line markers in ways that you never thought possible. So stay tuned :-)

 
Related posts:
  1. Draggable plot data-tips Matlab's standard plot data-tips can be customized to enable dragging, without being limitted to be adjacent to their data-point. ...
  2. Plot LineSmoothing property LineSmoothing is a hidden and undocumented plot line property that creates anti-aliased (smooth unpixelized) lines in Matlab plots...
  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. Controlling plot data-tips Data-tips are an extremely useful plotting tool that can easily be controlled programmatically....
 

Plot markers transparency and color gradient

$
0
0

Last week I explained how to customize plot-lines with transparency and color gradient. Today I wish to show how we can achieve similar effects with plot markers. Note that this discussion (like the preceding several posts) deal exclusively with HG2, Matlab’s new graphics system starting with R2014b (well yes, we can also turn HG2 on in earlier releases).

As Paul has noted in a comment last week, we cannot simply set a 4th (alpha transparency) element to the MarkerFaceColor and MarkerEdgeColor properties:

>> x=1:10; y=10*x; hLine=plot(x,y,'o-');
>> hLine.MarkerFaceColor = [0.5,0.5,0.5];      % This is ok
>> hLine.MarkerFaceColor = [0.5,0.5,0.5,0.3];  % Not ok
While setting the 'MarkerFaceColor' property of Line:
Color value must be a 3 element numeric vector

Standard Matlab plot markers

Standard Matlab plot markers

Lost cause? – not in a long shot. We simply need to be a bit more persuasive, using the hidden MarkerHandle property:

>> hMarkers = hLine.MarkerHandle;  % a matlab.graphics.primitive.world.Marker object
 
>> hMarkers.get
    EdgeColorBinding: 'object'
       EdgeColorData: [4x1 uint8]
       EdgeColorType: 'truecolor'
    FaceColorBinding: 'object'
       FaceColorData: [4x1 uint8]
       FaceColorType: 'truecolor'
    HandleVisibility: 'off'
             HitTest: 'off'
               Layer: 'middle'
           LineWidth: 0.5
              Parent: [1x1 Line]
       PickableParts: 'visible'
                Size: 6
               Style: 'circle'
          VertexData: [3x10 single]
       VertexIndices: []
             Visible: 'on'
 
>> hMarkers.EdgeColorData'  % 4-element uint8 array
ans =
    0  114  189  255
 
>> hMarkers.FaceColorData'  % 4-element uint8 array
ans =
  128  128  128  255

As we can see, we can separately attach transparency values to the marker’s edges and/or faces. For example:

hMarkers.FaceColorData = uint8(255*[1;0;0;0.3]);  % Alpha=0.3 => 70% transparent red

70% Transparent Matlab plot markers

70% Transparent Matlab plot markers

And as we have seen last week, we can also apply color gradient across the markers, by modifying the EdgeColorBinding/FaceColorBinding from ‘object’ to ‘interpolated’ (there are also ‘discrete’ and ‘none’), along with changing the corresponding FaceColorData/EdgeColorData from being a 4×1 array to a 4xN array:

>> colorData = uint8([210:5:255; 0:28:252; [0:10:50,40:-10:10]; 200:-10:110])
colorData =
  210  215  220  225  230  235  240  245  250  255
    0   28   56   84  112  140  168  196  224  252
    0   10   20   30   40   50   40   30   20   10
  200  190  180  170  160  150  140  130  120  110
 
>> set(hMarkers,'FaceColorBinding','interpolated', 'FaceColorData',colorData)

Matlab plot markers with color and transparency gradients

Matlab plot markers with color and transparency gradients

This can be useful for plotting comet trails, radar/sonar tracks, travel trajectories, etc. We can also use it to overlay meta-data information, such as buy/sell indications on a financial time-series plot. In fact, it opens up Matlab plots to a whole new spectrum of customizations that were more difficult (although not impossible) to achieve earlier.

Throughout today, we’ve kept the default FaceColorType/EdgeColorType value of ‘truecolor’ (which is really the same as ‘truecoloralpha’ as far as I can tell, since both accept an alpha transparency value as the 4th color element). If you’re into experimentation, you might also try ‘colormapped’ and ‘texturemapped’.

 
Related posts:
  1. Plot line transparency and color gradient Static and interpolated (gradient) colors and transparency can be set for plot lines in HG2. ...
  2. Plot LimInclude properties The plot objects' XLimInclude, YLimInclude, ZLimInclude, ALimInclude and CLimInclude properties are an important feature, that has both functional and performance implications....
  3. Draggable plot data-tips Matlab's standard plot data-tips can be customized to enable dragging, without being limitted to be adjacent to their data-point. ...
  4. Undocumented scatter plot jitter Matlab's scatter plot can automatically jitter data to enable better visualization of distribution density. ...
 

Another couple of Matlab bugs and workarounds

$
0
0

Every now and then I come across some internal Matlab bugs. In many cases I find a workaround and move on, sometimes bothering to report the bugs to MathWorks support, but often not. In truth, it’s a bit frustrating to hear the standard response that the issue [or "unexpected behavior", but never "bug" - apparently that's a taboo word] “has been reported to the development team and they will consider fixing it in one of the future releases of MATLAB”.

To date I’ve reported dozens of bugs and as far as I can tell, few if any of them have actually been fixed, years after I’ve reported them. None of them appear on Matlab’s official bug parade, which is only a small subset of the full list that MathWorks keeps hidden for some unknown reason (is it possible that someone’s ashamed of their bugs? nuh, couldn’t be…). Never mind, I don’t take it personally, I simply find a workaround and move on. I’ve already posted about this before. Today I’ll discuss two additional bugs I’ve run across once-too-often, and my workarounds:

Nothing really earth-shattering, but annoying nonetheless.

Saving non-Latin Command Window text using diary

The diary function is well-known for saving Matlab’s Command-Window (CW) text to a file. The function has existed for the past two decades at least, possibly even longer.

Unfortunately, perhaps the developer never thought that Matlab would be used outside the Americas and Western Europe, otherwise I cannot understand why to this day diary saves the text in ASCII format rather than the UTF-8 variant used by the CW. This works ok for basic Latin characters, but anyone who outputs Chinese, Japanese, Korean, Hindi, Arabic, Hebrew or other alphabets to the CW, and tries to save it using diary, will find the file unreadable.

Here is a sample illustrative script, that outputs the Arabic word salaam (peace, سلام) to the CW and then tries to save this using diary. If you try it, you will see it ok in the CW, but garbage text in the generated text file:

>> fname='diary_bug.txt'; diary(fname); disp(char([1587,1604,1575,1605])); diary off; winopen(fname)
سلام

The problem is that since diary assumes ASCII characters, any characters having a numeric value above 255 get truncated and are stored as invalid 1-byte characters, char(26) in this case.

Here’s my workaround:

% Output Command Window text to a text file
function saveCmdWinText(filename)
    cmdWinDoc = com.mathworks.mde.cmdwin.CmdWinDocument.getInstance;
    txt = char(cmdWinDoc.getText(0,cmdWinDoc.getLength));
    fid = fopen(filename,'W');
    fwrite(fid,txt,'uint16');  % store as 2-byte characters
    fclose(fid);
    %winopen(filename);  % in case you wish to verify...
end

This works well, saving the characters in their original 2-byte format, for those alphabets that use 2-bytes: non-basic Latins, Greek, Cyrillic, Armenian, Arabic, Hebrew, Coptic, Syriac and Tāna (I don’t think there are more than a handful Matlab users who use Coptic, Syriac or Tāna but never mind). However, UTF-8 specifies that CJK characters need 3-4 bytes and this is apparently not supported in Matlab, whose basic char data type only has 2 bytes, so I assume that Chinese, Japanese and Korean will probably require a different solution (perhaps the internal implementation of char and the CW is different in the Chinese/Japanese versions of Matlab, I really don’t know. If this is indeed the case, then perhaps a variant of my workaround can also be used for CJK output).

Also, this workaround is problematic in the sense that it’s a one-time operation that stores the entire CW text that is visible at that point. This is more limited than diary‘s ability to start and stop output recording in mid-run, and to record output on-the-fly (rather than only at the end). Still, it does provide a solution in case you output non-ASCII 2-byte characters to the CW.

There are various other bugs related to entering non-Latin (and specifically RTL) characters in the CW and the Matlab Editor. Solving the diary bug is certainly the least of these worries. Life goes on…

p.s. – I typically use this translator to convert from native script to UTF-8 codes that can be used in Matlab. I’m sure there are plenty of other translators, but this one does the job well enough for me.

For people interested in learning more about the Command Window internals, take a look at my cprintf and setPrompt utilities.

cprintf usage examples

cprintf usage examples

setPrompt usage examples

setPrompt usage examples

Printing GUIs reliably

Matlab has always tried to be far too sophisticated for its own good when printing figures. There’s plenty of internal code that tries to handle numerous circumstances in the figure contents for optimal output. Unfortunately, this code also has many bugs. Try printing even a slightly-complex GUI containing panels and/or Java controls and you’ll see components overlapping each other, not being printed, and/or being rendered incorrectly in the printed output. Not to mention the visible flicker that happens when Matlab modifies the figure in preparation for printing, and then modifies it back to the original.

All this when a simple printout of a screen-capture would be both much faster and 100% reliable.

Which is where my ScreenCapture utility comes in. Unlike Matlab’s print and getframe, ScreenCapture takes an actual screen-capture of an entire figure, or part of a figure (or even a desktop area outside any Matlab figure), and can then send the resulting image to a Matlab variable (2D RGB image), an image file, system clipboard, or the printer. We can easily modify the <Print> toolbar button and menu item to use this utility rather than the builtin print function:

Matlab's default toolbar Print action

Matlab's default toolbar Print action

hToolbar = findall(gcf,'tag','FigureToolBar');
hPrintButton = findall(hToolbar, 'tag','Standard.PrintFigure');
set(hPrintButton, 'ClickedCallback','screencapture(gcbf,[],''printer'')');
 
hPrintMenuItem = findall(gcf, 'type','uimenu', 'tag','printMenu');
set(hPrintMenuItem,      'Callback','screencapture(gcbf,[],''printer'')');

This prints the entire figure, including the frame, menubar and toolbar (if any). If you just wish to print the figure’s content area, then make sure to create a top-level uipanel that spans the entire content area and in which all the contents are included. Then simply pass this top-level container handle to ScreenCapture:

hTopLevelContainer = uipanel('BorderType','none', 'Parent',gcf, 'Units','norm', 'Pos',[0,0,1,1]);
...
hToolbar = findall(gcf,'tag','FigureToolBar');
hPrintButton = findall(hToolbar, 'tag','Standard.PrintFigure');
set(hPrintButton, 'ClickedCallback',@(h,e)screencapture(hTopLevelContainer,[],'printer'));
 
hPrintMenuItem = findall(gcf, 'type','uimenu', 'tag','printMenu');
set(hPrintMenuItem,      'Callback',@(h,e)screencapture(hTopLevelContainer,[],'printer'));

In certain cases (depending on platform/OS/Matlab-release), the result may capture a few pixels from the figure’s window frame. This can easily be corrected by specifying a small offset to ScreenCapture:

set(hPrintButton, 'ClickedCallback',@(h,e)printPanel(hTopLevelContainer));
set(hPrintMenuItem,      'Callback',@(h,e)printPanel(hTopLevelContainer));
 
function printPanel(hTopLevelContainer)
    pos = getpixelposition(hTopLevelContainer);
    screencapture(hTopLevelContainer, pos+[2,4,0,0], 'printer');
end

 
Related posts:
  1. A couple of internal Matlab bugs and workarounds A couple of undocumented Matlab bugs have simple workarounds. ...
  2. setPrompt – Setting the Matlab Desktop prompt The Matlab Desktop's Command-Window prompt can easily be modified using some undocumented features...
  3. Types of undocumented Matlab aspects This article lists the different types of undocumented/unsupported/hidden aspects in Matlab...
  4. Images in Matlab uicontrols & labels Images can be added to Matlab controls and labels in a variety of manners, documented and undocumented. ...
 

Transparency in uicontrols

$
0
0

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

 
Related posts:
  1. Images in Matlab uicontrols & labels Images can be added to Matlab controls and labels in a variety of manners, documented and undocumented. ...
  2. Panel-level uicontrols Matlab's uipanel contains a hidden handle to the title label, which can be modified into a checkbox or radio-button control...
  3. Plot line transparency and color gradient Static and interpolated (gradient) colors and transparency can be set for plot lines in HG2. ...
  4. Plot markers transparency and color gradient Matlab plot-line markers can be customized to have transparency and color gradients. ...
 

New book: Accelerating MATLAB Performance

$
0
0

I am pleased to announce that after three years of research and hard work, following my first book on Matlab-Java programming, my new book “Accelerating MATLAB Performance” is finally published.

Accelerating MATLAB Performance book
CRC promo code
The Matlab programming environment is often perceived as a platform suitable for prototyping and modeling but not for “serious” applications. One of the main complaints is that Matlab is just too slow.

Accelerating MATLAB Performance (CRC Press, ISBN 9781482211290, 785 pages) aims to correct this perception, by describing multiple ways to greatly improve Matlab program speed.

The book:

  • Demonstrates how to profile MATLAB code for performance and resource usage, enabling users to focus on the program’s actual hotspots
  • Considers tradeoffs in performance tuning, horizontal vs. vertical scalability, latency vs. throughput, and perceived vs. actual performance
  • Explains generic speedup techniques used throughout the software industry and their adaptation for Matlab, plus methods specific to Matlab
  • Analyzes the effects of various data types and processing functions
  • Covers vectorization, parallelization (implicit and explicit), distributed computing, optimization, memory management, chunking, and caching
  • Explains Matlab’s memory model and shows how to profile memory usage and optimize code to reduce memory allocations and data fetches
  • Describes the use of GPU, MEX, FPGA, and other forms of compiled code
  • Details acceleration techniques for GUI, graphics, I/O, Simulink, object-oriented Matlab, Matlab startup, and deployed applications
  • Discusses a wide variety of MathWorks and third-party functions, utilities, libraries, and toolboxes that can help to improve performance

Ideal for novices and professionals alike, the book leaves no stone unturned. It covers all aspects of Matlab, taking a comprehensive approach to boosting Matlab performance. It is packed with thousands of helpful tips, code examples, and online references. Supported by this active website, the book will help readers rapidly attain significant reductions in development costs and program run times.

Additional information about the book, including detailed Table-of-Contents, book structure, reviews, resources and errata list, can be found in a dedicated webpage that I’ve prepared for this book and plan to maintain.

Click here to get your book copy now!
Use promo code MZK07 for a 20% discount and free worldwide shipping on crcpress.com

Instead of focusing on just a single performance aspect, I’ve attempted to cover all bases at least to some degree. The basic idea is that there are numerous different ways to speed up Matlab code: Some users might like vectorization, others may prefer parallelization, still others may choose caching, or smart algorithms, or better memory-management, or compiled C code, or improved I/O, or faster graphics. All of these alternatives are perfectly fine, and the book attempts to cover every major alternative. I hope that you will find some speedup techniques to your liking among the alternatives, and at least a few new insights that you can employ to improve your program’s speed.

I am the first to admit that this book is far from perfect. There are several topics that I would have loved to explore in greater detail, and there are probably many speedup tips that I forgot to mention or have not yet discovered. Still, with over 700 pages of speedup tips, I thought this book might be useful enough as-is, flawed as it may be. After all, it will never be perfect, but I worked very hard to make it close enough, and I really hope that you’ll agree.

If your work relies on Matlab code performance in any way, you might benefit by reading this book. If your organization has several people who might benefit, consider inviting me for dedicated onsite training on Matlab performance and other advanced Matlab topics.

As always, your comments and feedback would be greatly welcome – please post them directly on the book’s webpage.

Happy Holidays everybody!

 
Related posts:
  1. Accelerating MATLAB Performance book Accelerating MATLAB Performance (ISBN 9781482211290) is a new book dedicated to improving Matlab code performance (speed). ...
  2. Matlab-Java memory leaks, performance Internal fields of Java objects may leak memory - this article explains how to avoid this without sacrificing performance. ...
  3. Matlab-Java book Undocumented Secrets of Matlab-Java Programming (ISBN 9781439869031) is a book dedicated to the integration of Matlab and Java. ...
  4. File deletion memory leaks, performance Matlab's delete function leaks memory and is also slower than the equivalent Java function. ...
 

2014 perspective & plans for 2015

$
0
0

With 2014 behind us and a fresh 2015 ahead, it is time again for a short look at this website’s achievements so far, and plans for the future.

I started this blog back in 2009, expecting the website to become just another a niche blog with a few geeky followers. 300 posts, 2800 reader comments, and 800K unique visitors apparently prove that Matlab’s advanced/undocumented features are important to a large portion of Matlab users. My pipeline of future articles continues to grow along with all other measurable quantities of website traffic.

Stats for nerds (and potential advertisers…)

Interest in this website grows steadily, continuing the trend from past years. To date, 794,000 unique readers, in 1.4 million visits, have read 2.5 million pages. The site’s audience grew, reaching over 11,000 unique visits (plus ~2000 RSS and email subscribers) per week. These figures are up about 40% from last year, a solid growth rate that keeps surprising me. In the following graph, the traffic dips are due to the annual December holidays. The growth trend is quite evident:

Steady readership growth (click for details)

Steady readership growth (click for details)

At the current rate, sometime in 2015 this blog will pass the million-visitors mark. How significant are the absolute numbers? I believe that my 2012 analysis still remains valid, so please refer there.

2014 in review

In 2014, I published 40 articles, including:

As can be seen, quite a few posts deal with performance, which is one of my favorite topics, and the topic of my latest book. I expect to post more articles on this topic in 2015.

Writing a well-researched article takes time and effort. Unfortunately, I wasn’t able in 2014 to keep the pace of a weekly article from past years, as you can see from the summary list (Archives) on the right. I hope I’ll be able to do better in 2015. There’s no shortage of material, only too few hours per day and too few days per week…

Guest bloggers

2014 continued the trend in previous years of hosting articles by guest bloggers:

If you have any Matlab topic with an undocumented twist, I will be happy to post your contents here as well. Don’t be shy – email me (altmany at gmail) and I’ll help with the details.

Plans for 2015

I plan to continue posting about undocumented aspects of Matlab. Specific plans include additional articles on HG2 and performance aspects. I also hope to cross out additional items in my TODO list. Two long-overdue mini-series that I hope to get around to, are about Matlab-database connectivity and Matlab’s new toolstrip/ribbon.

Concurrently with the posts, I will continue to provide professional Matlab consulting and contract work for clients. If you have an interesting project that could use professional Matlab programming, please let me know.

In addition, I plan to develop commercial connector products to a couple of online services. My IB-Matlab product (connecting Matlab with Interactive Brokers) is very popular and I hope to have time to release other similar products.

Training

Finally, I plan to continue providing advanced Matlab training courses/seminars. During the past year I provided customized on-site training courses in multiple locations, including Norway, Germany, Switzerland, Israel and USA.

If you are dealing with any advanced Matlab programming (if you read this blog then you probably do), consider inviting me for custom on-site training to improve your team’s capabilities. This is a unique opportunity to enhance your Matlab skills in a few days, at an affordable cost, by an established expert. If you have a specific topic that you would like me to discuss, then I would be happy to do it. In other words, I can customize the training to your specific needs, within the provided timeframe. Such advanced training is not provided anywhere else, and you’d be surprised at how cost effective this could be. If you are interested, please email me (altmany at gmail) for details.

Happy 2015 everybody!

- Yair Altman

 
Related posts:
  1. 2013 perspective & plans for 2014 2013 has seen a continued steady growth in website content and readership. This post takes an overview of past achievements and future plans. ...
  2. 2012 perspective & plans for 2013 2012 has seen a continued steady growth in website content and readership. This post takes an overview of past achievements and future plans. ...
  3. 2011 perspective & plans for 2012 2011 has seen a continued steady growth in readership of this website. This post takes an overview of past achievements and future plans. ...
  4. 2010 perspective & plans for 2011 2009 and 2010 have seen steady growth in readership of this website. This post takes an overview of past achievements and future plans....
 

Unorthodox checkbox usage

$
0
0

A few weeks ago, Robert Cumming explained how we can use a Matlab uicontrol’s CData property to provide an optical illusion of a transparent background. Today I will discuss another usage of this property, providing a simple checkbox control the unorthodox appearance of a split-pane divider.

The underlying problem description is easy: we wish to have the ability to split a Matlab uipanel into two or more sub-panels, separated by a draggable horizontal/vertical divider. Such split-panes are standard in any semi-decent GUI, but for some reason were never incorporated in official Matlab. This is a real pity, but not to worry as there are at least two alternatives we could use:

UISplitPane

UISplitPane is a utility that I wrote back in 2009 that uses a Java JSplitPane divider and associates it with plain Matlab panels on both sides. This solves the problem of embedding Matlab axes in Java panels, such as the ones provided by the standard Java JSplitPane. A detailed description of the technique can be found in my dedicated post on this utility.

Two levels of UISplitPane, with customized dividers

Two levels of UISplitPane, with customized dividers

[hDown,hUp,hDiv1] = uisplitpane(gcf, 'Orientation','ver', 'dividercolor',[0,1,0]);
[hLeft,hRight,hDiv2] = uisplitpane(hDown, 'dividercolor','r', 'dividerwidth',3);
t=0:.1:10; 
hax1=axes('Parent',hUp);    plot(t,sin(t));
hax2=axes('parent',hLeft);  plot(t,cos(t));
hax3=axes('parent',hRight); plot(t,tan(t));
hDiv1.DividerLocation = 0.75;    % one way to modify divider properties...
set(hDiv2,'DividerColor','red'); % ...and this is another way...

Making UISplitPane work in HG2 (R2014b onward) was quite a pain: numerous changes had to be made. For example, dynamic UDD properties can no longer be added to Matlab handles, only to Java ones. For Matlab handles, we now need to use the addprop function. For such properties, the UDD meta-property SetFunction is now called SetMethod (and similarly for Get) and only accepts function handles (not function handle cells as in UDD). Also, the UDD meta-property AccessFlags.PublicSet='off' needed to change to SetAccess='private'. Also, handle.listener no longer works; instead, we need to use the addlistener function. There are quite a few other similar tweaks, but UISplitPanenow hopefully works well on both old (HG1, R2014a and earlier) and new (HG2, R2014b+) Matlab releases. Let me know if you still see unhandled issues.

UIExtras flex-box

UIExtras (officially named “GUI Layout Toolbox”) is a toolbox of very useful GUI handling functions related to layout management. Written within MathWorks and originally posted in 2010, it has been under continuous maintenance ever since. While being called a “toolbox”, it is in fact freely-downloadable from the Matlab File Exchange.

The new HG2 introduced in R2014b did not just make code porting difficult for me – uiextras’ developers (MathWorkers Ben Tordoff and David Sampson) also encountered great difficulties in porting the code and making sure that it is backward compatible with HG1. In the end they gave up and we now have two distinct versions of the toolbox: the original version for HG1 (R2014a and earlier) and a new version for HG2 (R2014b+).

In my opinion, uiextras is one of the greatest examples of Matlab code on the File Exchange. It is well-written, well-documented and highly performant (although I would also have preferred it to be a bit more robust, it sometimes complains when used). Readers could benefit greatly by studying its techniques, and today’s subject topic is one such example. Specifically, the split-pane divider in uiextras (used by HBoxFlex and VBoxFlex) is simply a Matlab uicontrol having a custom CData property. This CData value is computed and set programmatically (at the bottom of uix.Divider) to display a flat color with some markings at the center (“hand-holds”, a visual cue for interactive dragging, which can be turned off if requested). Thus, for a vertical divider (for an HBoxFlex container) of height 100 pixels and width of 5 pixels, we would get a CData of 100x5x3 (x3 for RGB colors):

hHBox = uiextras.HBoxFlex('Spacing',6, 'BackgroundColor','b');  % Spacing=6 means divider width =6px, and CData width =5px
hLeft  = uicontrol('parent',hHBox, 'style','check', 'string','Left split pane');
hRight = uicontrol('parent',hHBox, 'style','radio', 'string','Right split pane');

UIExtras HBoxFlex with draggable split-pane divider

UIExtras HBoxFlex with draggable split-pane divider

The divider handle is a private property, so we cannot readily access it. However, as I have explained last year, we can use the builtin struct function:

oldWarn = warning('off','MATLAB:structOnObject');  % temporarily disable warning message on discouraged usage
hHBox_data = struct(hHBox);  % this includes hidden/private properties
warning(oldWarn);
hDividers = hHBox_data.Dividers;  % multiple dividers are possible in HBoxFlex/VBoxFlex
cdata = get(hDividers(1), 'CData');

A very nice trick here is that this divider uicontrol is not a pushbutton as we might have expected. Instead, it is a checkbox control. And while it does not look anything like a standard checkbox (due to the custom CData), checkboxes (and radio-buttons) have a very important advantage that caused them to be preferable over buttons: in buttons, there is always a small border showing at the control’s edges, but checkboxes do not have any 3D appearance, or in other words they do not have a border — their CData can span the entire extent of the control. Neat, right?

This enables us to customize the appearance of checkboxes (and radios) to any arbitrary shape, by setting the relevant CData pixels to transparent/bgcolor (as Robert showed last week for buttons). Matlab GUI controls no longer need to look a boring rectangle. We can have clickable stars, draggable icons, and other similar uses. This really opens up the possibilities for rich GUI appearance. If anyone uses this feature, please do post a comment below (preferably with a nice screenshot!).

 
Related posts:
  1. Tri-state checkbox Matlab checkboxes can easily be made to support tri-state functionality....
  2. Profiling Matlab memory usage mtic and mtoc were a couple of undocumented features that enabled users of past Matlab releases to easily profile memory usage. ...
  3. IB-Matlab usage examples Access market/portfolio data and submit trade orders in Matlab via Interactive Brokers (IB). IB-Matlab provides an easy-to-use Matlab interface to InteractiveBrokers, enabling quants, algo traders and ordinary folk to easily...
  4. UISplitPane UISplitPane was recently chosen as Matlab Central's Pick of the Week. Here I detail its use of some undocumented Matlab features....
 

export_fig

$
0
0

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.

 
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. Plot markers transparency and color gradient Matlab plot-line markers can be customized to have transparency and color gradients. ...
  4. Plot line transparency and color gradient Static and interpolated (gradient) colors and transparency can be set for plot lines in HG2. ...
 

Matlab compiler bug and workaround

$
0
0

I recently consulted at a client who uses R2010a and compiles his code for distribution. Debugging compiled code is often tricky, since we do not have the Matlab desktop to help us debug stuff (well, actually we do have access to a scaled-down desktop for minimal debugging using some undocumented internal hooks, but that’s a topic for a separate article). In my client’s case, I needed to debug a run-time error that threw an exception to the console:

Error using strtrim
Input should be a string or a cell array of strings.
Error in updateGUI (line 121)

Sounds simple enough to debug right? Just go to updateGUI.m line #121 and fix the call to strtrim(), correct?

Well, not so fast… It turns out that updateGUI.m line #121 is an empty line surrounded on either side by one-line comments. This is certainly not the line that caused the error. The actual call to strtrim() only occurs in line #147!

What’s going on?

The answer is that the Matlab compiler has a bug with comment blocks – lines surrounded by %{ and %}:

15   %{
16       This is a comment block that is
17       ignored by the Matlab engine,
18       and causes a line-numbering
19       error in the Matlab compiler!
20   %}
21 
22   a = strtrim(3.1416);  % this generates an error

In the example above, the 6-line comment block is ignored as expected by the Matlab engine in both interactive and compiled modes. However, whereas in interactive mode the error is correctly reported for line #22, in compiled mode it is reported for line #17. Apparently the compiler replaces any block comment with a single comment line before parsing the m-file.

The workaround is simple: count all the block-comment lines that precede the reported error line in the original m-file, and add that number to the reported line. In the example above, 17 + (6-1) = 22. Note that the source code could have multiple block-comments that precede the reported line, and they should all be counted. Here is a basic code snippet that does this parsing and opens the relevant m-file at the correct location:

% Read the source file (*.m)
str = fileread(filename,'*char');
 
% Split the contents into separate lines
lines = strtrim(strsplit(str',10));
 
% Search for comment block tokens
start_idx = find(strcmp(lines,'%{'));
end_idx   = find(strcmp(lines,'%}'));
 
% Count the number of block-comment lines in the source code
delta_idx = end_idx - start_idx;
relevant_idx = sum(start_idx < reported_line_number);
total_comment_block_lines = sum(delta_idx(1:relevant_idx));
 
% Open the source file at the correct line
opentoline(filename, reported_line_number + total_comment_block_lines);

This code snippet can fairly easily be wrapped in a stand-alone utility by anyone who wishes to do so. You’d need to generate the proper full-path source-code (m-file) filename of course, since this is not reported by the deployed application in its error message. You’d also need to take care of edge-cases such as p-coded or mex files, or missing source-code m-files. You’d also need to parse the input parameters (presumably filename and reported_line_number, but possibly also other inputs).

I’m not sure on which Matlab releases this specific compiler bug occurs (in addition to R2010a), but I would be surprised if it does not still exist to this day (Update: according to comments below, this bug was apparently fixed some years ago). Unfortunately I don’t have a Matlab compiler handy, but users who do have one should be able to easily test this on various Matlab releases. If you do, then please let us all know in a comment below.

This is another example of a bug that does not officially exist in Matlab’s public bug parade (at least, I couldn’t find it). I’ve reported other such undocumented bugs in previous articles (here and here). Please don’t start another comments tirade on MathWorks’ bug-publication policies. I think that issue has already been discussed ad nauseam.

Another related bug related to block comments is that at least on some Matlab releases (I haven’t tested properly to determine which releases), block comments are NOT properly ignored by the Editor’s publish functionality. Instead, at least on those releases where the bug occurs, publishing code that includes block comments parses the block’s contents as if it was runnable code. In other words, publish treats %{ and %} as one-line comments rather than as tokens marking the ends of a block comment.

 
Related posts:
  1. Bug and workaround in timeseries plot Matlab's internal hgconvertunits function has a bug that affects timeseries plots. Luckily there is a simple workaround....
  2. A couple of internal Matlab bugs and workarounds A couple of undocumented Matlab bugs have simple workarounds. ...
  3. Another couple of Matlab bugs and workarounds A couple of internal Matlab bugs and their workarounds. ...
  4. Solving a Matlab hang problem A very common Matlab hang is apparently due to an internal timing problem that can easily be solved. ...
 

Accessing hidden HG2 plot functionality

$
0
0

I received two separate reader queries in the past 24 hours, asking how to access certain functionalities in HG2 (R2014b)’s new graphics system. These functionalities were previously accessible in HG1 (R2014a and earlier), but stopped being [readily] accessible in HG2. The functionalities have not disappeared, they have merely changed the way in which they can be accessed. Moreover, with the new graphics system they were even expanded in terms of their customizability.

In both cases, the general way in which I approached the problem was the same, and I think this could be used in other cases where you might need some HG1 functionality which you cannot find how to access in HG2. So try to read today’s article not as a specific fix to these two specific issues, but rather as a “how-to” guide to access seemingly inaccessible HG2 features.

Accessing contour fills

Contour fills were implemented in HG1 as separate HG objects that could be accessed using findall or allchild. This could be used to set various properties of the fills, such as transparency. This broke in HG2 as reported by reader Leslie: the contours are no longer regular HG children. No complaints there – after all, it was based on undocumented internal features of the data-brushing functionality.

It turns out that the solution for HG2 is not difficult, using the contour handle’s hidden FacePrims property:

[~, hContour] = contourf(peaks(20), 10);
drawnow;  % this is important, to ensure that FacePrims is ready in the next line!
hFills = hContour.FacePrims;  % array of matlab.graphics.primitive.world.TriangleStrip objects
for idx = 1 : numel(hFills)
   hFills(idx).ColorType = 'truecoloralpha';   % default = 'truecolor'
   hFills(idx).ColorData(4) = 150;   % default=255
end

Contour plot in HG2, with and without transparency

Contour plot in HG2, with and without transparency


The contour fills are now stored as an array of TriangleStrip objects, which can be individually customized:

>> get(hFills(1))
             AmbientStrength: 0.3
             BackFaceCulling: 'none'
                ColorBinding: 'object'
                   ColorData: [4x1 uint8]
                   ColorType: 'truecoloralpha'
             DiffuseStrength: 0.6
            HandleVisibility: 'on'
                     HitTest: 'off'
                       Layer: 'middle'
               NormalBinding: 'none'
                  NormalData: []
                      Parent: [1x1 Contour]
               PickableParts: 'visible'
    SpecularColorReflectance: 1
            SpecularExponent: 10
            SpecularStrength: 0.9
                   StripData: [1 4 11 14 19 25 28 33]
                     Texture: []
            TwoSidedLighting: 'off'
                  VertexData: [3x32 single]
               VertexIndices: []
                     Visible: 'on'

Accessing plot brushed data

In October 2010 I published an article explaining how to programmatically access brushed data in Matlab plots (brushed data are highlighted data points using the interactive data-brushing tool on the figure toolbar). Apparently, data brushing was implemented as a data line having only the data-brushed points in its data, and using dedicated markers. This worked well in HG1, until it too broke in HG2, as reported by reader bash0r.

It turns out that in HG2, you can access the brushing data using the plot line’s hidden BrushHandles property, as follows:

hBrushHandles = hLine.BrushHandles;
hBrushChildrenHandles = hBrushHandles.Children;  % Marker, LineStrip

I described the new Marker objects here, and LineStrip objects here. The brushed vertex data can be retrieved from either of them. For example:

>> hBrushChildrenHandles(1).VertextData
ans = 
     1     2     3     4     % X-data of 4 data points
     1     2     3     4     % Y-data of 4 data points
     0     0     0     0     % Z-data of 4 data points

If you only need the brushed data points (not the handles for the Markers and LineStrip, you can get them directly from the line handle, using the hidden BrushData property:

>> brushedIdx = logical(hLine.BrushData);  % logical array (hLine.BrushData is an array of 0/1 ints)
>> brushedXData = hLine.XData(brushedIdx);
>> brushedYData = hLine.YData(brushedIdx)
brushedYData =
     1     2     3     4

Data brushing in HG2

Data brushing in HG2

A general “how-to” guide

In order to generalize these two simple examples, we see that whereas the HG objects in HG1 were relatively “flat”, in HG2 they became much more complex objects, and their associated functionality is now embedded within deeply-nested properties, which are in many cases hidden. So, if you find a functionality for which you can’t find a direct access via the documented properties, it is very likely that this functionality can be accessed by some internal hidden property.

In order to list such properties, you can use my getundoc utility, or simply use the built-in good-ol’ struct function, as I explained here. For example:

>> warning('off','MATLAB:structOnObject')  % turn off warning on using struct() on an object. Yeah, we know it's bad...
>> allProps = struct(hContour)
allProps = 
                 FacePrims: [11x1 TriangleStrip]
             FacePrimsMode: 'auto'
               FacePrims_I: [11x1 TriangleStrip]
                 EdgePrims: [10x1 LineStrip]
             EdgePrimsMode: 'auto'
               EdgePrims_I: [10x1 LineStrip]
                 TextPrims: []
             TextPrimsMode: 'auto'
               TextPrims_I: []
             ContourMatrix: [2x322 double]
         ContourMatrixMode: 'auto'
           ContourMatrix_I: [2x322 double]
             ContourZLevel: 0
         ContourZLevelMode: 'auto'
           ContourZLevel_I: 0
                      Fill: 'on'
                  FillMode: 'auto'
                    Fill_I: 'on'
                      Is3D: 'off'
                  Is3DMode: 'auto'
                    Is3D_I: 'off'
              LabelSpacing: 144
                       ...   % (many more properties listed)

This method can be used on ALL HG2 objects, as well as on any internal objects that are referenced by the listed properties. For example:

>> allProps = struct(hContour.FacePrims)
allProps = 
             StripDataMode: 'manual'
               StripData_I: [1 4 11 14 19 25 28 33]
                 StripData: [1 4 11 14 19 25 28 33]
       BackFaceCullingMode: 'auto'
         BackFaceCulling_I: 'none'
           BackFaceCulling: 'none'
      FaceOffsetFactorMode: 'manual'
        FaceOffsetFactor_I: 0
          FaceOffsetFactor: 0
        FaceOffsetBiasMode: 'manual'
          FaceOffsetBias_I: 0.0343333333333333
            FaceOffsetBias: 0.0343333333333333
      TwoSidedLightingMode: 'auto'
        TwoSidedLighting_I: 'off'
          TwoSidedLighting: 'off'
                   Texture: []
               TextureMode: 'auto'
                       ...   % (many more properties listed)

In some cases, the internal property may not be directly accessible as object properties, but you can always access them via the struct (for example, allProps.StripData).

Do you use any HG1 functionality in your code that broke in HG2? Did my “how-to” guide above help you recreate the missing functionality in HG2? If so, please share your findings with all of us in a comment below.

 
Related posts:
  1. Accessing plot brushed data Plot data brushing can be accessed programmatically using very simple pure-Matlab code...
  2. Performance: accessing handle properties Handle object property access (get/set) performance can be significantly improved using dot-notation. ...
  3. Plot line transparency and color gradient Static and interpolated (gradient) colors and transparency can be set for plot lines in HG2. ...
  4. Controlling plot data-tips Data-tips are an extremely useful plotting tool that can easily be controlled programmatically....
 

Simulink Data Dictionary

$
0
0

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(sectionName, commandString)
hDict.assignin(sectionName, 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.

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

 
Related posts:
  1. Improving Simulink performance Simulink simulation run-time performance can be improved by orders of magnitude by following some simple steps. ...
  2. Sparse data math info Matlab contains multiple libraries for handling sparse data. These can report very detailed internal info. ...
  3. Draggable plot data-tips Matlab's standard plot data-tips can be customized to enable dragging, without being limitted to be adjacent to their data-point. ...
  4. Controlling plot data-tips Data-tips are an extremely useful plotting tool that can easily be controlled programmatically....
 

Customizing Matlab uipanels

$
0
0

The major innovation in Matlab release R2014b was the introduction of the new handle-based graphics system (HG2). However, this release also included a few other improvements to graphics/GUI that should not be overlooked. The most notable is that uitabs are finally officially documented/supported, following a decade or being undocumented (well, undocumented in the official sense, since I took the time to document this functionality in this blog and in my Matlab-Java book).

A less-visible improvement occurred with uipanels: Panels are very important containers when designing GUIs. They enable a visual grouping of related controls and introduce order to an otherwise complex GUI. Unfortunately, until R2014b panels were drawn at the canvas level, and did not use a standard Java Swing controls like other uicontrols. This made it impossible to customize uipanels in a similar manner to other GUI uicontrols (example).

In R2014b, uipanels have finally become standard Java Swing controls, a com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel component that extends Swing’s standard javax.swing.JPanel and Matlab’s ubiquitous com.mathworks.mwswing.MJPanel. This means that we can finally customize it in various ways that are not available in plain Matlab.

We start the discussion with a simple Matlab code snippet. It is deliberately simple, since I wish to demonstrate only the panel aspects:

figure('Menubar','none', 'Color','w');
hPanel = uipanel('Title','Panel title', 'Units','norm', 'Pos',[.1,.1,.6,.7]);
hButton = uicontrol('String','Click!', 'Parent',hPanel);

Standard Matlab uipanel

Standard Matlab uipanel

Notice the default ‘etchedin’ panel border, which I hate (note the broken edges at the corners). Luckily, Swing includes a wide range of alternative borders that we can use. I’ve already demonstrated customizing Matlab uicontrols with Java borders back in 2010 (has it really been that long? wow!). In R2014b we can finally do something similar to uipanels:

The first step is to get the uipanel‘s underlying Java component’s reference. We can do this using my findjobj utility, but in the specific case of uipanel we are lucky to have a direct shortcut by using the panel’s undocumented hidden property JavaFrame and its PrintableComponent property:

>> jPanel = hPanel.JavaFrame.getPrintableComponent
jPanel =
com.mathworks.hg.peer.ui.UIPanelPeer$UIPanelJPanel[,0,0,97x74,...]

Let’s now take a look at the jPanel‘s border:

>> jPanel.getBorder
ans =
com.mathworks.hg.peer.ui.borders.TitledBorder@25cd9b97
 
>> jPanel.getBorder.get
                Border: [1x1 com.mathworks.hg.peer.ui.borders.EtchedBorderWithThickness]
          BorderOpaque: 0
                 Class: [1x1 java.lang.Class]
                 Title: 'Panel title'
            TitleColor: [1x1 java.awt.Color]
             TitleFont: [1x1 java.awt.Font]
    TitleJustification: 1
         TitlePosition: 2

Ok, simple enough. Let’s replace the border’s EtchedBorderWithThickness with something more appealing. We start with a simple red LineBorder having rounded corners and 1px width:

jColor = java.awt.Color.red;  % or: java.awt.Color(1,0,0)
jNewBorder = javax.swing.border.LineBorder(jColor, 1, true);  % red, 1px, rounded=true
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

Rounded-corners LineBorder

Rounded-corners LineBorder

Or maybe a thicker non-rounded orange border:

jColor = java.awt.Color(1,0.5,0);
jNewBorder = javax.swing.border.LineBorder(jColor, 3, false);  % orange, 3px, rounded=false
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

Another LineBorder example

Another LineBorder example

Or maybe a MatteBorder with colored insets:

jColor = java.awt.Color(0,0.3,0.8);  % light-blue
jNewBorder = javax.swing.border.MatteBorder(2,5,8,11,jColor)  % top,left,bottom,right, color
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

MatteBorder with solid insets

MatteBorder with solid insets

MatteBorder can also use an icon (rather than a solid color) to fill the border insets. First, let’s load the icon. We can either load a file directly from disk, or use one of Matlab’s standard icons. Here are both of these alternatives:

% Alternative #1: load from disk file
icon = javax.swing.ImageIcon('C:\Yair\star.gif');
 
% Alternative #2: load a Matlab resource file
jarFile = fullfile(matlabroot,'/java/jar/mlwidgets.jar');
iconsFolder = '/com/mathworks/mlwidgets/graphics/resources/';
iconURI = ['jar:file:/' jarFile '!' iconsFolder 'favorite_hoverover.png'];  % 14x14 px
icon = javax.swing.ImageIcon(java.net.URL(iconURI));

We can now pass this icon reference to MatteBorder‘s constructor:

w = icon.getIconWidth;
h = icon.getIconHeight;
jNewBorder = javax.swing.border.MatteBorder(h,w,h,w,icon)  % top,left,bottom,right, icon
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

MatteBorder with icon insets

MatteBorder with icon insets

Additional useful Swing borders can be found in the list of classes implementing the Border interface, or via the BorderFactory class. For example, let’s create a dashed border having a 3-2 ratio between the line lengths and the spacing:

jColor = java.awt.Color.blue;  % or: java.awt.Color(0,0,1);
lineWidth = 1;
relativeLineLength = 3;
relativeSpacing = 2;
isRounded = false;
jNewBorder = javax.swing.BorderFactory.createDashedBorder(jColor,lineWidth,relativeLineLength,relativeSpacing,isRounded);
jPanel.getBorder.setBorder(jNewBorder);
jPanel.repaint;  % redraw the modified panel

StrokeBorder (dashed)

StrokeBorder (dashed)

After seeing all these possibilities, I think you’ll agree with me that Matlab’s standard uipanel borders look pale in comparison.

Have you used any interesting borders in your Matlab GUI? Or have you customized your panels in some other nifty manner? If so, then please place a comment below.

 
Related posts:
  1. Transparent uipanels Matlab uipanels can be made transparent, for very useful effects. ...
  2. Customizing Matlab labels Matlab's text uicontrol is not very customizable, and does not support HTML or Tex formatting. This article shows how to display HTML labels in Matlab and some undocumented customizations...
  3. Customizing uicontrol border Matlab uicontrol borders can easily be modified - this article shows how...
  4. Customizing editboxes Matlab's editbox can be customized in many useful manners...
 

Transparent legend

$
0
0

I’ve been working lately on Matlab program for a client, which attempts to mimic the appearance and behavior of MetaTrader charts, which are extensively used by traders to visualize financial timeseries and analysis indicators.

Such charts are often heavily laden with information, and a legend can be handy to understand the meaning of the various plot lines. Unfortunately, in such heavily-laden charts the legend box typically overlaps the data. We can of course move the legend box around (programmatically or by interactive dragging). But in such cases it might be more useful to have the legend background become semi- or fully-transparent, such that the underlying plot lines would appear beneath the legend:

Matlab chart with a semi-transparent legend (click for details)
Matlab chart with a semi-transparent legend (click for details)

A few months ago I explained the undocumented feature of setting the transparency level of plot lines by simply specifying a fourth numeric (alpha) value to the Color property. Unfortunately, this technique does not work for all graphic objects. For example, setting a 4th (alpha) value to the MarkerFaceColor property results in an error. In the case of legends, setting a 4th (alpha) value to the legend handle’s Color property does not result in an error, but is simply ignored.

The solution in the case of legends is similar in concept to that of the MarkerFaceColor property, which I explained here. The basic idea is to use one of the legend’s hidden properties (in this case, BoxFace) in order to access the low-level color properties (which I have already explained in previous posts):

>> hLegend = legend(...);
>> hLegend.Color = [0.5, 0.5, 0.5, 0.8];  % should be 20%-transparent gray, but in fact opaque gray
 
>> hLegend.BoxFace.get
             AmbientStrength: 0.3
             BackFaceCulling: 'none'
                ColorBinding: 'object'
                   ColorData: [4x1 uint8]
                   ColorType: 'truecolor'
             DiffuseStrength: 0.6
            HandleVisibility: 'on'
                     HitTest: 'off'
                       Layer: 'back'
               NormalBinding: 'none'
                  NormalData: []
                      Parent: [1x1 Group]
               PickableParts: 'visible'
    SpecularColorReflectance: 1
            SpecularExponent: 10
            SpecularStrength: 0.9
                   StripData: []
                     Texture: []
            TwoSidedLighting: 'off'
                  VertexData: [3x4 single]
               VertexIndices: []
                     Visible: 'on'
 
>> hLegend.BoxFace.ColorData  % 4x1 uint8
ans =
  128
  128
  128
  255   % this is the alpha value

As can be seen from this code snippet, the RGB ingredients (but not the alpha value) of Color have passed through to the BoxFace‘s ColorData. The problem stems from BoxFace‘s default ColorType value of 'truecolor'. Once we set it to 'truecoloralpha', we can set ColorData‘s alpha value to a value between uint8(0) and uint8(255):

set(hLegend.BoxFace, 'ColorType','truecoloralpha', 'ColorData',uint8(255*[.5;.5;.5;.8]));  % [.5,.5,.5] is light gray; 0.8 means 20% transparent
Opaque (default) legend20% transparent legend50% transparent legend
0% transparent (default)20% transparent50% transparent
ColorData = [128;128;128;255][128;128;128;204][128;128;128;128]

Note 1: ColorData only accepts a column-vector of 4 uint8 values between 0-255. Attempting to set the value to a row vector or non-uint8 values will result in an error.

Note 2: once we update the BoxFace color, the legend’s standard Color property loses its connection to the underlying BoxFace.ColorData, so updating hLegend.Color will no longer have any effect.

BoxFace.ColorType also accepts 'colormapped' and 'texturemapped' values; the BoxFace.ColorBinding accepts values of 'none', 'discrete' and 'interpolated', in addition to the default value of 'object'. Readers are encouraged to play with these values for colorful effects (for example, gradient background colors).

Finally, note that this entire discussion uses Matlab’s new graphics engine (HG2), on R2014b or newer.

If you’ve found any other interesting use of these undocumented/hidden legend properties, please share it in a comment below. If you’d like me to develop a custom GUI (such as the charting program above or any other GUI) for you, please contact me by email or using my contact form.

 
Related posts:
  1. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
  2. Transparent uipanels Matlab uipanels can be made transparent, for very useful effects. ...
  3. Plot line transparency and color gradient Static and interpolated (gradient) colors and transparency can be set for plot lines in HG2. ...
  4. Plot markers transparency and color gradient Matlab plot-line markers can be customized to have transparency and color gradients. ...
 

Frameless (undecorated) figure windows

$
0
0

All Matlab figures have a standard frame around them, consisting of a border and title bar. In some cases it could be useful to present a figure window, displaying only the contents without the border and title bar. Such a borderless (undecorated) window is not possible in Matlab. Well, at least not in supported/documented Matlab…

Readers of this blog and/or my Matlab-Java programming book are aware that Matlab’s GUI is based on Java Swing. In the end, every Matlab figure window is a simple Java JFrame, and JFrames have a setUndecorated(true) method that can be called to remove the border and title bar.

An undecorated Matlab figure window
An undecorated Matlab figure window

Attempt #1 – direct invocation

Unfortunately, we cannot directly call setUndecorated in Matlab, because it only works when the JFrame has not yet been displayed:

% Get the figure's underlying Java JFrame reference handle
>> mjf = get(handle(gcf), 'JavaFrame');
>> jWindow = mjf.fHG2Client.getWindow  % or: mjf.getAxisComponent.getTopLevelAncestor
jWindow =
com.mathworks.hg.peer.FigureFrameProxy$FigureFrame[fClientProxyFrame,740,-761,576x509,...]
 
% Try to remove decoration
>> jWindow.setUndecorated(true)
Java exception occurred:
java.awt.IllegalComponentStateException: The frame is displayable.
	at java.awt.Frame.setUndecorated(Unknown Source)

On the other hand, if we try to call setUndecorated on a new invisible figure then we’d see that the JFrame component is not yet created by Matlab:

% Create a simple Matlab figure
hFig = figure('Name','Plot example', 'Visible','off');
 
% Get the underlying Java JFrame reference handle (empty)
>> mjf = get(handle(hFig),'JavaFrame');
>> jWindow = mjf.getAxisComponent.getTopLevelAncestor
jWindow =
     []
>> jWindow = mjf.fHG2Client.getWindow
jWindow =
     []
 
>> jWindow.setUndecorated(true)
Attempt to reference field of non-structure array.

So we have a catch-22 situation: we can’t call setUndecorated until the JFrame is created, but Matlab only creates it when it displays the figure window, and then it’s too late to undecorate…

Attempt #2 – reparenting: an optical illusion

One way that I found around this problem is to reparent the Matlab JFrame‘s content onto a pure Java JFrame that has been made undecorated. To hide the Matlab figure after creating the JFrame, we can simply move the figure’s position to be outside the visible monitor area:

% Create a simple Matlab figure (visible, but outside monitor area)
t = 0 : 0.01 : 10;
hFig = figure('Name','Plot example', 'ToolBar','none', 'MenuBar','none');
hLine = plot(t, cos(t));
hButton = uicontrol('String','Close', 'Position',[307,0,45,16]);
 
% Ensure that everything is rendered, otherwise the following will fail
drawnow;
 
% Get the underlying Java JFrame reference handle
mjf = get(handle(hFig), 'JavaFrame');
jWindow = mjf.fHG2Client.getWindow;  % or: mjf.getAxisComponent.getTopLevelAncestor
 
% Get the content pane's handle
mjc = jWindow.getContentPane;
mjr = jWindow.getRootPane;  % used for the offset below
 
% Create a new pure-Java undecorated JFrame
figTitle = jWindow.getTitle;
jFrame = javaObjectEDT(javax.swing.JFrame(figTitle));
jFrame.setUndecorated(true);
 
% Move the JFrame's on-screen location just on top of the original
jFrame.setLocation(mjc.getLocationOnScreen);
 
% Set the JFrame's size to the Matlab figure's content size
%jFrame.setSize(mjc.getSize);  % slightly incorrect by root-pane's offset
jFrame.setSize(mjc.getWidth+mjr.getX, mjc.getHeight+mjr.getY);
 
% Reparent (move) the contents from the Matlab JFrame to the new JFrame
jFrame.setContentPane(mjc);
 
% Make the new JFrame visible
jFrame.setVisible(true);
 
% Hide the Matlab figure by moving it off-screen
pos = get(hFig,'Position');
set(hFig, 'Position',[-1000,-1000,pos(3:4)]);
drawnow;

Matlab figures are not pure JFrame but rather a subclass (com.mathworks.widgets.desk.DTSingleClientFrame). So instead of creating a new JFrame, we could create a new instance of Matlab’s class instead, potentially solving a few problems:

jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
jFrame = javaObjectEDT(com.mathworks.widgets.desk.DTSingleClientFrame(jDesktop, figTitle));
% ...the rest is exactly the same as above...

Either way, we now get a nice undecorated window containing our Matlab contents (see screenshot above).

Once the undecorated JFrame becomes visible, we should not hide or delete the original Matlab figure, because this will stop rendering of the contents.

Working with the undecorated frame

We can modify the Matlab figure and its contents normally, just as if they still appeared within the original Matlab figure. This can be used to display a dynamic application splash-screen, that displays information on various initialization/loading steps. Or alternately we could use it to display a system health-monitor (small panel with red/green indicators), or maybe a graph with streaming market data or live news alerts. The usages are endless, limited only by your imagination, not by Matlab.

For example, let’s modify our plot dynamically using a timer, and set the close button’s callback to dismiss the new JFrame and original figure:

% Set a timer to dynamically update the plot every 0.1 sec
start(timer('TimerFcn', {@timerCallback,hLine}, 'ExecutionMode','fixedRate', 'Period',0.1));
 
% Set the close button callback
set(hButton, 'Callback',{@closeCallback,jFrame});
 
% This is the close button's callback
function closeCallback(hButton, eventData, jFrame)
   delete(ancestor(hButton,'figure'));
   dispose(jFrame);
end
 
% This is the plot timer's callback
function timerCallback(hTimer, eventData, hLine)
   xdata = get(hLine,'XData') + 0.1;
   set(hLine, 'XData',xdata, 'YData',cos(xdata));
   xlim([min(xdata) max(xdata)]);
end

Note: if you don’t hide the toolbar/menubar in the original Matlab figure, some of their functions will not work properly in the new JFrame (e.g., zoom, pan etc.). But in most use-cases we do not want a toolbar/menubar in an undecorated window. The example above showed an undecorated window without the toolbar/menubar.

If we wish to avoid having the new JFrame appear in the Operating System’s taskbar, we can use the following command:

jFrame.setType(javaMethod('valueOf','java.awt.Window$Type','UTILITY'))

Note that this command must be executed before the JFrame is made visible. Also note that it only works with Java 7, in other words Matlab R2013b (8.2) or newer (or if you are very adventurous and happen to use an older Matlab with a custom Java 7 installation).

But now that there is no taskbar component, how can we transfer focus to our new undecorated window? In other words, if another windows hides our new undecorated frame, how can we get it back on top?

A simple solution is to set the Matlab figure frame’s FocusGainedCallback to requestFocus for the newly created jFrame. Then, when we click the Matlab figure’s button on the taskbar, the new jFrame will pop into focus. In effect, this provides the optical illusion that the taskbar button refers to the undecorated window (since the actual Matlab figure is positioned beyond the monitor’s area):

hjWindow = handle(jWindow, 'CallbackProperties');
set(hjWindow, 'FocusGainedCallback', @(h,e)jFrame.requestFocus);

Likewise, we should instrument our Matlab figure so that when it is closed/deleted, so too is our new jFrame:

set(hjWindow, 'WindowClosedCallback', @(h,e)jFrame_.dispose);

undecorateFig and redecorateFig

I have encapsulated all of the above in a couple of very easy-to-use utilities that I just posted on the Matlab File Exchange: undecorateFig, redecorateFig. Using them can’t get any simpler than this:

undecorateFig;        % undecorate the current figure (gcf)
undecorateFig(hFig);  % hFig is any GUI handle (needs to be visible)
 
redecorateFig;        % redecorate the current figure (gcf)
redecorateFig(hFig);  % hFig is any GUI handle

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

Have you made some interesting use of this nice feature in your application? If so, please share it in a comment below.

A suggested related mini project for anyone interested: add an image reflection of the current figure contents beneath the figure. You could use my ScreenCapture utility or directly use java.awt.Robot.createScreenCapture(mjc.getLocationOnScreen), process the resulting image (blur, apply transparency gradient, crop at 50% height etc.) and place the resulting image within an undecorated JFrame placed directly beneath the main figure. You can instrument the figure (hjWindow)’s ComponentMovedCallback and ComponentResizedCallback to move/resize the reflection JFrame whenever the parent figure moves or is resized. You could use a timer to periodically update the reflection image so that it remains synchronized with the parent. You’ll probably also want to add a nice toggle-button to the figure’s toolbar to turn the reflection on/off. Maybe I’ll hack this project someday when I have some spare time. Or maybe someone will beat me to it… Care to try?

 
Related posts:
  1. Minimize/maximize figure window Matlab figure windows can easily be maximized, minimized and restored using a bit of undocumented magic powder...
  2. Transparent Matlab figure window Matlab figure windows can be made fully or partially transparent/translucent or blurred - this article explains how...
  3. Blurred Matlab figure window Matlab figure windows can be blurred using a semi-transparent overlaid window - this article explains how...
  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. ...
 

Using Infiniband with Matlab Parallel Computing Toolbox

$
0
0

I would like to welcome guest blogger Brock Palen, who is the Associate Director for Advanced Research Computing at the University of Michigan. Brock worked in High Performance computing since 2004 and is also one half of the Research Computing podcast; Research Computing and Engineering. You can find him blogging at failureasaservice.com. This is an updated repost of Brock’s article on UMich’s Flux HPC blog. Additional information on the Parallel Computing Toolbox can be found in my book Accelerating MATLAB Performance.

In High Performance Computing (HPC) there are a number of network types commonly used, among these are: Ethernet, the common network found on all computer equipment. Infiniband, a specialty high performance low latency interconnect common on commodity clusters. There are also several propriety types and a few other less common types but I will focus on Ethernet and Infiniband.

Ethernet and really its mate protocol, TCP, are the most common supported MPI networks. Almost all computer platforms support this network type and can be as simple as using your home network switch. It is ubiquitous and easy to support. Networks like Infiniband though require special drivers, uncommon hardware but the effort is normally worth it.

The MATLAB Parallel Computing Toolbox provides a collection of functions that allow MATLAB users to utilize multiple compute nodes to work on larger problems. Many may not realize that MathWorks chose to use the standard MPI routines to implement this toolbox. MathWorks also chose, for ease of use, to ship MATLAB with the MPICH2 MPI library, and the version they use only supports Ethernet for communication between nodes.

Unfortunately, Ethernet is about the slowest common network used in parallel applications. The question is how much can this impact performance.

Mmmmm Data:

The data was generated on 12 nodes of Xeon x5650 total 144 cores. The code was the stock MATLAB paralleldemo_backslash_bench(1.25) from MATLAB 2013b. You can find my M-code at Gist.

The data shows two trends: the first is that independently of the network type, many parallel algorithms do not scale unless the amount of data for each core to work on is sufficiently large. In this case, for Ethernet especially, the peak performance is never reached. What should be really noted though is that without Infiniband, at many problem sizes, over half of the performance of the nodes is lost. The second trend is that the network type really matters.

How to have MATLAB use Infiniband?

MathWorks does not ship an MPI library with the parallel computing toolbox that can use infiniband by default. This is reasonable, I would be curious how large the average PCT cluster is, and/or how big the jobs ran on the toolbox are. Lucky for us MathWorks allows a way for introducing your own MPI library. Let me be the first to proclaim:

Thank you MathWorks for adding mpiLibConf.m as a feature.
— Brock Palen

A simple example (note that MATLAB’s local scheduler also uses mpiLibConf, so we need to check for this case):

function [lib, extras] = mpiLibConf
%MATLAB MPI Library overloading for Infiniband and Ethernet Networks
%
%USAGE
%   place in ~/matlab/mpiLibConf.m
%   Update to point to your MPICH / Intel MPI etc location
 
% Check first if we're running the local scheduler - if we are, then get the default and exit
dfcn = getenv('MDCE_DECODE_FUNCTION');
if strcmp(dfcn, 'parallel.internal.decode.localMpiexecTask')
    % Get the local scheduler's default libs
    [lib, extras] = distcomp.mpiLibConfs('default');
else
    % We're not running the local scheduler or using the default MATLAB libmpich
    lib = '/home/software/rhel6/mvapich2/1.8/lib/libmpich.so';
 
    % mvapich has two extra libraries libmpl.so and libopa.so
    %  use # ldd /home/software/rhel6/mvapich2/1.8/lib/libmpich.so
    %   Any libraries from the mpich/mvapich install location need to be included in extras
    extras = {'/home/software/rhel6/mvapich2/1.8/lib/libmpl.so',
              '/home/software/rhel6/mvapich2/1.8/lib/libopa.so'};
end

In the above test we used Intel MPI for the infiniband test and mpich for the ethernet test. The choice of MPI is important. The MPI standard enforces a shared API (Application programming interface), but not a shared ABI (Application binary interface). Thus the MPI library you substitute needs to match the one MATLAB is compiled against. Lucky for us they used mpich, so any mpich clone should work; MVAPICH, IntelMPI, etc.

If you are using the MATLAB Parallel Computing Toolbox on more than one node, and if your cluster has a network other than Ethernet/TCP (there are non-TCP Ethernet networks that perform very well) I highly encourage that the effort be put in to ensure you use that network.

For Flux users we have this setup, but you have to do some setup for yourself before you see the benefit. Please visit the ARC MATLAB documentation, or send us a question at hpc-support@umich.edu.

 
Related posts:
  1. Explicit multi-threading in Matlab part 2 Matlab performance can be improved by employing .Net (C#, VB, F# or C++) threads. ...
  2. Explicit multi-threading in Matlab part 4 Matlab performance can be improved by employing timer objects and spawning external processes. ...
  3. Explicit multi-threading in Matlab part 3 Matlab performance can be improved by employing POSIX threads in C/C++ code. ...
  4. Matlab compiler bug and workaround Both the Matlab compiler and the publish function have errors when parsing block-comments in Matlab m-code. ...
 

Plot legend title

$
0
0

This blog post was supposed to be a piece of cake: The problem description was that we wish to display a text title next to the legend box in plot axes. Sounds simple enough. After all, in HG1 (R2014a and earlier), a legend was a simple wrapper around a standard Matlab axes. Therefore, we can simply access the legend axes’s title handle, and modify its properties. This works very well in HG1:

hold all; 
hLine1 = plot(1:5); 
hLine2 = plot(2:6); 
hLegend = legend([hLine1,hLine2], 'Location','NorthWest');
hTitle = get(hLegend,'title');
set(hTitle, 'String','Plot types:', 'VerticalAlignment','middle', 'FontSize',8);

Matlab HG1 legend with title

Matlab HG1 legend with title

HG2

How hard then could a corresponding solution be in HG2 (R2014b+), right?

Well, it turns out that hard enough (at least for me)…

In this blog I’ve presented ~300 posts so far that discuss solutions to problems. Readers of this blog always hear the success stories, and might mistakenly think that every problem has a similarly simple solution that can be hacked away in a few lines of nifty code.

Well, the truth must be told that for each investigation that yields such a success story, there is at least one other investigation in which I failed to find a solution, no matter how hard I tried or countless hours spent digging (this is not to say that the success stories are easy – distilling a solution to a few lines of code often takes hours of research). In any case, maybe some of these problems for which I have not found a solution do have one that I have simply not discovered, and maybe they don’t – in most likelihood I will never know.

This is yet another example of such a spectacular failure on my part. Try as I may in HG2, I could find no internal handle anywhere to the legend’s axes or title handle. As far as I could tell, HG2′s legend is an standalone object of class matlab.graphics.illustration.Legend that derives from exactly the same superclasses as axes:

>> sort(superclasses('matlab.graphics.axis.Axes'))
ans = 
    'JavaVisible'
    'dynamicprops'
    'handle'
    'matlab.graphics.Graphics'
    'matlab.graphics.GraphicsDisplay'
    'matlab.graphics.internal.GraphicsJavaVisible'
    'matlab.mixin.CustomDisplay'
    'matlab.mixin.Heterogeneous'
    'matlab.mixin.SetGet'
>> sort(superclasses('matlab.graphics.illustration.Legend'))
ans = 
    'JavaVisible'
    'dynamicprops'
    'handle'
    'matlab.graphics.Graphics'
    'matlab.graphics.GraphicsDisplay'
    'matlab.graphics.internal.GraphicsJavaVisible'
    'matlab.mixin.CustomDisplay'
    'matlab.mixin.Heterogeneous'
    'matlab.mixin.SetGet'

This make sense, since they share many properties/features. But it also means that legends are apparently not axes but rather unrelated siblings. As such, if MathWorks chose to remove the Title property from the legend object, we will never find it.

So what can we do in HG2?

Well, we can always resort to the poor-man’s solution of an optical illusion: displaying a an invisible axes object having the same Position as the legend box, with an axes title. We attach property listeners on the legend’s Units, Position and Visible properties, linking them to the corresponding axes properties, so that the title will change if and when the legend’s properties change (for example, by dragging the legend to a different location, or by resizing the figure). We also add an event listener to destroy the axes (and its title) when the legend is destroyed:

% Create the legend
hLegend = legend(...);  % as before
 
% Create an invisible axes at the same position as the legend
hLegendAxes = axes('Parent',hLegend.Parent, 'Units',hLegend.Units, 'Position',hLegend.Position, ...
                   'XTick',[] ,'YTick',[], 'Color','none', 'YColor','none', 'XColor','none', 'HandleVisibility','off', 'HitTest','off');
 
% Add the axes title (will appear directly above the legend box)
hTitle = title(hLegendAxes, 'Plot types:', 'FontWeight','normal', 'FontSize',8);  % Default is bold-11, which is too large
 
% Link between some property values of the legend and the new axes
hLinks = linkprop([hLegend,hLegendAxes], {'Units', 'Position', 'Visible'});
% persist hLinks, otherwise they will stop working when they go out of scope
setappdata(hLegendAxes, 'listeners', hLinks);
 
% Add destruction event listener (no need to persist here - this is done by addlistener)
addlistener(hLegend, 'ObjectBeingDestroyed', @(h,e)delete(hLegendAxes));

Matlab HG2 legend with title

Matlab HG2 legend with title

Yes, this is indeed a bit of an unfortunate regression from HG1, but I currently see no other way to solve this. We can’t win ‘em all… If you know a better solution, I’m all ears. Please shoot me an email, or leave a comment below.

Update: As suggested below by Martin, here is a more elegant solution, which attaches a text object as a direct child of the legend’s hidden property DecorationContainer (we cannot add it as a child of the legend since this is prevented and results in an error):

hLegend = legend(...);
hlt = text(...
    'Parent', hLegend.DecorationContainer, ...
    'String', 'Title', ...
    'HorizontalAlignment', 'center', ...
    'VerticalAlignment', 'bottom', ...
    'Position', [0.5, 1.05, 0], ...
    'Units', 'normalized');

The title appears to stay attached to the legend and the Parent property of the text object even reports the legend object as its parent:

hLegend.Location = 'southwest';  % Test the title's attachment
hlt.Parent % Returns hLegend

- thanks Martin!

Happy Passover/Easter everybody!

 
Related posts:
  1. Transparent legend Matlab chart legends are opaque be default but can be made semi- or fully transparent. ...
  2. Multi-column (grid) legend This article explains how to use undocumented axes listeners for implementing multi-column plot legends...
  3. Bar plot customizations Matlab bar charts can be customized in various nifty ways. ...
  4. Plot LimInclude properties The plot objects' XLimInclude, YLimInclude, ZLimInclude, ALimInclude and CLimInclude properties are an important feature, that has both functional and performance implications....
 

Handle object as default class property value

$
0
0

We all know the benefits of setting default class-property values: it saves coding, increases class readability, improves maintainability and reduces the potential for coding bugs due to uninitialized properties. Basically, we’re setting default values of the class properties, so that whenever a new instance of this class is created, it will be recreated with these same default property values. This is the behavior in any self-respecting OOP language, and is a well-entrenched paradigm in OOP computing. Simple enough, right?

Well, unfortunately it doesn’t behave quite this way in Matlab…

Problem example

First, define class Internal as follows:

classdef Internal < hgsetget & matlab.mixin.Copyable
    properties
        Value = 0
    end
 
    methods
        function obj = Internal()
        end
        function set.Value(obj, newValue)
            obj.Value = newValue;
        end
        function str = char(obj)
            str = sprintf('Internal [Value=%s]', mat2str(obj.Value));
        end
        function disp(obj)
            disp(char(obj));
        end
    end
 
    methods (Static)
        function obj = getDefault()
            obj = Internal();
        end
    end
end

Now define class External as follows:

classdef External < hgsetget & matlab.mixin.Copyable
    properties
        MyValue = Internal.getDefault;
    end
 
    methods
        function obj = External(varargin)
            % empty constructor
        end
        function set.MyValue(obj, newValue)
            obj.MyValue = newValue;
        end
        function str = char(obj)
            str = sprintf('External [MyValue = %s]', char(obj.MyValue));
        end
        function disp(obj)
            disp(char(obj));
        end
    end
end

Now run the following (note the highlighted unexpected internal value):

>> clear classes
>> e1 = External
e1 = 
External [MyValue = Internal [Value=0]]
 
>> e1.MyValue.Value = 1
e1 = 
External [MyValue = Internal [Value=1]]
 
>> e2 = External   % This returns a bad value of 1 (should be 0!)
e2 = 
External [MyValue = Internal [Value=1]] 
>> e1 == e2   % this proves that e1~=e2 (as expected)
ans =
     0
 
>> Internal.getDefault   % this proves that the default Internal value remains unchanged (as expected)
ans = 
Internal [Value=0]

Basically, this shows that setting e1.MyValue.Value=1 has also affected future class constructions, such that e2=External (which should have created a new handle object with a default property value of 0) now returns the modified value 1.

How is this possible?

The answer lies in the fine print of the documentation:

    Evaluation of property default values occurs only when the value is first needed, and only once when MATLAB first initializes the class. MATLAB does not reevaluate the expression each time you create a class instance.

In other words, when Matlab first loads the External class code into memory (typically upon its first instance creation), it assigns the handle reference to a new Internal instance to the class property. This same handle reference (memory pointer, in a broad sense) is used for all subsequent creations of External class instances. So basically, all instances of External share the same Internal object!

This does not affect properties that are initialized to primitive (non-object) data, nor to value classes (as opposed to handle classes). The reason is that Matlab’s built-in COW (copy-on-write) mechanism ensures that we get a new copy of a value class whenever one of its properties is modified. However, this does not happen in handle classes, so modifying Internal‘s property in one instance of External also affects the other instances.

So yes, it’s fully documented (sort of). But confusing? Counter-intuitive? Unexpected? – you bet!

In recent releases, Matlab increasingly relies on MCOS (Matlab’s latest OOP incarnation) for its internal codebase. I venture a guess that if a poll was made among MathWorker developers, the majority (if not vast majority) of them are not aware of this fine detail. Certainly programmers who come from other programming languages would not expect this behavior. This raises a concern that any internal Matlab object that has properties which are handle objects might incur hard-to-trace bugs due to this behavior.

Workaround and plea for action

At the moment, the only workaround is to programmatically set the property’s default value to a new instance of the handle class in the classes constructor. So, in our case, we would modify External‘s constructor as follows:

classdef External < hgsetget & matlab.mixin.Copyable
    properties
        MyValue  % no misleading default value here!    end
 
    methods
        function obj = External(varargin)
            % non-empty constructor
            obj.MyValue = Internal.getDefault;        end
...

I strongly urge MathWorks to modify this unexpected behavior (and certainly the documentation). I believe that the vast majority of MCOS users would welcome a change to the expected behavior, i.e., create a new Internal object at instance creation time rather than just at class-load time. Moreover, I bet that it would save many internal bugs in Matlab’s own code, which is probably by far the largest MCOS codebase worldwide…

I’m the first one to complain about backward incompatibilities, but in this particular case I think that it’s not an important concern since users should never rely on this “feature” in their code – it would be bad programming for so many reasons.

Reference: G1308623

 
Related posts:
  1. Class object creation performance Performance aspects of Matlab class object creation are discussed, with specific suggestions. ...
  2. Getting default HG property values Matlab has documented how to modify default property values, but not how to get the full list of current defaults. This article explains how to do this. ...
  3. Class object tab completion & improper field names Tab completions and property access can be customized for user-created Matlab classes. ...
  4. Setting class property types Matlab's class properties have a simple and effective mechanism for setting their type....
 

Undocumented view transformation matrix

$
0
0

Everyone knows Matlab’s view function, right? You know, the function that can set a 3D plot to the proper orientation angles and/or return the current plot’s azimuth/elevation angles. I’ve used it numerous times myself in the past two decades. It’s one of Matlab’s earliest functions, dating back to at least 1984. Still, as often as I’ve used it, it was not until I came across Bruce Elliott’s post on CSSM last week that I realized that this seamingly-innocent stock Matlab function holds a few interesting secrets.

view()’s transformation matrix output

First, while view‘s 2-output syntax ([az,el]=view()) is well known and documented, there is also a single-output syntax (T=view()) that is neither. To be exact, this syntax is not mentioned in the official documentation pages, but it does appear in the help section of view.m, which is viewable (no pun intended…) if you type the following in your Matlab console (R2014a or earlier, note the highlighted lines):

>> help view
 view   3-D graph viewpoint specification.
    view(AZ,EL) and view([AZ,EL]) set the angle of the view from which an
    observer sees the current 3-D plot.  AZ is the azimuth or horizontal
    rotation and EL is the vertical elevation (both in degrees). Azimuth
    revolves about the z-axis, with positive values indicating counter-
    clockwise rotation of the viewpoint. Positive values of elevation
    correspond to moving above the object; negative values move below.
    view([X Y Z]) sets the view angle in Cartesian coordinates. The
    magnitude of vector X,Y,Z is ignored.
 
    Here are some examples:
 
    AZ = -37.5, EL = 30 is the default 3-D view.
    AZ = 0, EL = 90 is directly overhead and the default 2-D view.
    AZ = EL = 0 looks directly up the first column of the matrix.
    AZ = 180 is behind the matrix.
 
    view(2) sets the default 2-D view, AZ = 0, EL = 90.
    view(3) sets the default 3-D view, AZ = -37.5, EL = 30.
 
    [AZ,EL] = view returns the current azimuth and elevation.
 
    T = view returns the current general 4-by-4 transformation matrix. 
    view(AX,...) uses axes AX instead of the current axes.
 
    See also viewmtx, the axes Properties view, Xform. 
    Reference page in Help browser
       doc view
 
>> surf(peaks); T=view
T =
      0.79335     -0.60876            0    -0.092296
      0.30438      0.39668      0.86603     -0.78354
       0.5272      0.68706         -0.5       8.3031
            0            0            0            1

Note that the extra highlighted information is probably a documentation oversight by some MathWorker many years ago, since it was removed from the help section in R2014b and does not appear in the doc pages (not even in R2014a). Perhaps it was documented in the early years but then someone for who-knows-what-reason decided that it shouldn’t be, and then forgot to remove all the loose ends until R2014b. Or maybe it was this way from the very beginning, I don’t know.

In any case, just to be clear on this, the transformation matrix out is still returned by view in the latest Matlab release (R2015a), just as it has for the past who-knows-how-many releases.

There are several interesting things to note here:

view()’s vs. viewmtx()’s transformation matrices

First, MathWorks have still not done a good job of removing all loose ends. Specifically, the T=view syntax is discussed in the doc page (and help section) of the viewmtx function.

To make things worse (and even more confusing), the usage example shown in that doc page is wrong: it says that view(az,el); T=view returns the same transformation matrix T as T=viewmtx(az,el). Close, but not the same:

>> view(30,60); T=view
T =
      0.86603          0.5            0     -0.68301
     -0.43301         0.75          0.5     -0.40849
        -0.25      0.43301     -0.86603       9.0018
            0            0            0            1
>> T2=viewmtx(30,60)
T2 =
      0.86603          0.5            0            0
     -0.43301         0.75          0.5            0
         0.25     -0.43301      0.86603            0
            0            0            0            1

Tough luck I guess for anyone who relies on viewmtx‘s output for complex 3D graphics…

T and T2 appear to be related via a transformation matrix (XT=[1,0,0,0; 0,1,0,0; 0,0,-1,0; 0,0,0,1], we’ll use it again below) that fixes the signs of the first 3 columns, and another translation matrix (camera viewpoint?) that provides the 4th column of T.

HG1′s undocumented axes transformation properties

Another tidbit that should never have been placed in view‘s help section in the first place, is the reference to the axes property Xform (read: “transform”, not “X-Form”). Xform is a hidden undocumented property, and as far as I can tell has always been this way. It is therefore surprising to see it mentioned in the official help section of a highly-visible function such as view. In fact, I don’t remember any other similar case.

In HG1 (R2014a and earlier), the axes’ Xform property held the transformation matrix that view returns. Alongside Xform, the HG1 axes contained several additional transformation vectors (x_RenderOffset, x_RenderScale) and matrices (x_NormRenderTransform, x_ProjectionTransform, x_RenderTransform, x_ViewPortTransform, x_ViewTransform – the latter (x_ViewTransform) is the same as Xform) that could be used for various purposes (example, technical details). All of these properties were removed in HG2 (R2014b or newer).

A complete usage example for some of these properties can be found in MathWorker Joe Conti’s select3d utility, which was removed from the File exchange, but can still be found online (note that it croacks on HG2=R2014b+ due to the removal of the hidden properties):

function [p] = local_Data2PixelTransform(ax,vert)
% Transform vertices from data space to pixel space.
 
% Get needed transforms
xform  = get(ax,'x_RenderTransform');
offset = get(ax,'x_RenderOffset');
scale  = get(ax,'x_RenderScale');
 
% Equivalent: nvert = vert/scale - offset;
nvert(:,1) = vert(:,1)./scale(1) - offset(1);
nvert(:,2) = vert(:,2)./scale(2) - offset(2);
nvert(:,3) = vert(:,3)./scale(3) - offset(3);
 
% Equivalent xvert = xform*xvert;
w = xform(4,1) * nvert(:,1) + xform(4,2) * nvert(:,2) + xform(4,3) * nvert(:,3) + xform(4,4);
xvert(:,1) = xform(1,1) * nvert(:,1) + xform(1,2) * nvert(:,2) + xform(1,3) * nvert(:,3) + xform(1,4);
xvert(:,2) = xform(2,1) * nvert(:,1) + xform(2,2) * nvert(:,2) + xform(2,3) * nvert(:,3) + xform(2,4);
 
% w may be 0 for perspective plots 
ind = find(w==0);
w(ind) = 1; % avoid divide by zero warning
xvert(ind,:) = 0; % set pixel to 0
 
p(:,1) = xvert(:,1) ./ w;
p(:,2) = xvert(:,2) ./ w;

We could even set these hidden properties directly, as Bruno Luong showed back in 2009 (the bug he reported in the R2009b prerelease was temporary, it still worked ok in R2014a):

set(gca,'Xform',eye(4))

HG2′s transformations

In HG2 (R2014b onward), we no longer have access to the hidden properties above. I’m still not exactly sure how to get all the transformations above, but at least the following can be used to replicate the transformation matrix T:

% "standard" way to get the transformation matrix
T = view;
 
% internal way
XT = [1,0,0,0; 0,1,0,0; 0,0,-1,0; 0,0,0,1];
hCamera = get(gca, 'Camera');
T = XT * GetViewMatrix(hCamera);

I’m guessing there are probably similar ways to get the other transformation matrices, but I’ll leave that as an exercise to the reader. Anyone who is up to the task is welcome to leave a comment below. Don’t come asking for my help here – I’m off to solve another puzzle. After all, there’s only a week left before my next blog post is due, so I better get started.

In summary, MathWorks have apparently done some cleanup for the new HG2 in R2014b, but I guess there’s still some work left to do (at least on the documentation). More importantly, much more work is needed to provide simple documented/supported ways of doing 3D transformations without banging our heads at all these hidden corners. Or maybe there already is such a way and I’m simply not aware of it, there’s always that possibility…

 
Related posts:
  1. Matrix processing performance Matrix operations performance is affected by internal subscriptions in a counter-intuitive way....
  2. getundoc – get undocumented object properties getundoc is a very simple utility that displays the hidden (undocumented) properties of a specified handle object....
  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. Undocumented scatter plot jitter Matlab's scatter plot can automatically jitter data to enable better visualization of distribution density. ...
 
Viewing all 219 articles
Browse latest View live