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

Customizing axes rulers

$
0
0

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

Customized HG2 plot

Customized HG2 plot


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

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

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

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

Axes Rulers

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

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

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

Axle property

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

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

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

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

The result can be seen in the screenshot above.

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

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

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

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

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

Exponent and SecondaryLabel properties

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

hAxes.YRuler.Exponent = -3;

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

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

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

The result can be seen in the screenshot above.

Call for action

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

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


Viewing all articles
Browse latest Browse all 219

Trending Articles