Using a computed axis title in a graph

Revision as of 22:51, 11 June 2021 by Lchrisman (talk | contribs) (fixed a hyperlink problem)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Requires Analytica 6.0 or later

On this page, I show an example of how you can display a computed axis title. By doing so, you can dynamically change your axis title text as a user changes a slicer, so that the graph for each slice uses a different axis title.

In the current example, we will include the currently selected value of an index named Metric in the Y-Axis title, when the graph is pivoted so that Metric is slicer. You can see this in these screenshots as I use the slicer to select different Metric values:

Computed axis title Rider.pngComputed axis title Driver.png

Because the axis title is computed by any Analytica expression you want to come up with, your computed title could depend on just about anything, changing with the specific values in the data, the uncertainty view, the specific pivot, and so on. Also, you can use the same approach to set a graph key title (such as for a color key) to computed text.

You may want to download this example as you follow along: Computed Axis Title includes Slicer value.ana

Computing title in the OnGraphDraw attribute

I compute the axis title in the OnGraphDraw attribute during the "before drawing" phase.

To use the OnGraphDraw attribute in your own model, you need to make it visible from the Attributes dialog on the Object menu.

The OnGraphDraw attribute accepts an expression, just like a Definition of a variable accepts an expression, but this expression gets computed while the graph is being rendered. Many aspects of the graph can change between when your variable's main result finishes computing and the graph itself is displayed. For example, a user might change the uncertainty view, pivot axes, change graphing roles such as color or symbol, or change slicer values. You can get access to the current values of these by putting your expressions inside OnGraphDraw, and in addition, your code can alter certain aspects of the graph from OnGraphDraw.

Phase

The OnGraphDraw expression can be evaluated up to 4 times, at 4 distinct phases of drawing. To change the axis title, your expression needs to change the title on of the first two phases, "before layout" or "before drawing". If you were to change it in the "after axes, before data" phase, it would be too late since the axes are already drawn. In the Object Window, you can select the phase:

OnGraphDraw PhaseBeforeAxes and after.png

When you select only one phase, your code doesn't need to include conditional logic based on the phase, since it will be run only once. If your OnGraphDraw code is doing multiple things, you may need to enable multiple phases, in which case you could surround the code developed here inside If phase=2 Then ( «code in this article» ). By so doing, you won't incur the inefficiency of running the same code multiple times. The phases are numbered 1, 2, 4 and 8. Since I am enabling only one phase, I don't include this test here.

To actually change the title, your code will assign to the local variable «roleChanges», which is one of the locals provided to the OnGraphDraw attribute.

Accessing the Slicer position

We want to use the currently selected value of Metric in our title, so we need to access the slicer for the Metric index and determine which value is currently selected. This is accomplished with the following two lines in OnGraphDraw:

Local slicers := #info[ OnGraphDrawItem='SlicerPositions'];
Local pos := slicers[.Slicer=Handle(Metric)];

Note that Metric is the name of our index in our model. OnGraphDrawItem is a system index that indexes the local variable info. The local info is pre-defined by the graphing engine before evaluating OnGraphDraw, and contains a large amount of information about the graph being drawn (see OnGraphDrawItem for the list of what is there).

The first line extracts an array containing all the slicers and their positions, the second line extracts the currently selected position for the slicer for Metric. If the pivot is changed so that Metric is no longer a slicer, pos will be Null.

Computing the axis title text

Once we know the selected position, the expression Slice(Metric, pos) returns the selected index value. (Aside: In the case of a self-indexed array, you would need to use Slice(IndexValue(Metric),pos).) Hence, we can now compute our axis title text using a Formatted Text Literal as

f"Cost for {Slice(Metric,pos)}"

Changing the axis title

To change the axis title in the graph to our computed value, we assign to the appropriate cell of roleChanges:

roleChanges[ GraphingRole='Y axis', GraphFillerInfo='Title'] :=
f"Cost for {Slice(Metric,pos)}"

Since it doesn't make sense to change the title when Metric is not a slicer, I surround this in a If pos<>NullThen ...

Putting it all together

The full OnGraphDraw expression is thus

Local slicers := #info[ OnGraphDrawItem='SlicerPositions'];
Local pos := slicers[.Slicer=Handle(Metric)];
If pos<>Null Then
roleChanges[ GraphingRole='Y axis', GraphFillerInfo='Title'] :=
f"Cost for {Slice(Metric,pos)}"

Packaging as a User-Defined Function (UDF)

Once you've perfected an OnGraphDraw effect like this, you may want to encapsulate it in as a UDF. Doing so reduces the logic in your OnGraphDraw attribute to a single function call, making it easy to re-use if you want to do the same thing it a second place. Perhaps even more important, next time you won't have to remember how you did it, since that is encapsulated in the UDF.

One possible way to encapsulate this as a UDF is shown here:

Axis title from slicer encapsulated as UDF.png

With this UDF, your OnGraphDraw becomes just one line:

roleChanges := AxisTitleFromSlicer( info, roleChanges, Metric, "cost of %L%" )

The model file for this example includes this UDF and usage, along with a second approach for encapsulation not covered here.

See Also

Comments


You are not allowed to post comments.