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
The contour fills are now stored as an array of
TriangleStripobjects, 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
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
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,
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.
Using struct may not be the optimal solution; I, personally, prefer your uiinspect utility due to its graphical and interactive interface. One must not forget your instrumental FindJObj and checkClass utilities for inspecting java objects.
On another matter: the data cursors in HG2 have TeX interpretation capabilities. It had been a default option in the non-official HG2 releases (Matlab R2013b with “
-hgVersion 2” startup); however, it has been removed in the official Matlab R2014b release. Using the
uiinspectfunction, I found the
Interpreterresiding in the
DataCursor. To re-enable it use simply:
If one wishes to use just the interactive data cursors, they can simply change the
UpdateFcnof the data cursor mode:
It is such a simple and useful feature; I wish that TMW made it documented and accessible…
These days, I typically use the
metaclassfunction for this kind of thing.
That list of properties in PropertyList includes 178 of the 181 properties that you found with
struct(the missing ones apparently being “SerializableChildren”, “SerializableUIContextMenu”, and “TopLevelSerializedObject”). Using
metaclasswon’t give you GetAccess to properties which deny it like
structdoes, but at least for base MATLAB graphics classes, the list of properties with private or protected GetAccess is usually very small and properties that you probably don’t need anyway (that contour object has 6 properties with protected GetAccess: “SerializableApplicationData”, “SerializableBehavior”, “CreateFcn_IS”, “DeleteFcn_IS”, “ButtonDownFcn_IS”, and “SerializableUserData”).
The benefits of using the
metaclassfunction are that it gives you access to a lot more information: property attributes (Hidden, GetAccess, etc), methods (including hidden ones), and even pointers to the meta.class objects of superclasses inherited by the object in question.