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
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
>> 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.
>> 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.