7. Chart declarations

The plotting at the end of a forecast round is always the same twenty lines. Pick a range, loop over names, subplot, plot, title, grid, shade the forecast span, repeat for the next scenario. It gets written fresh in every project, it is never quite the same twice, and it is the part of a round most likely to be wrong in a way nobody notices.

rise.plot.rcharts replaces it with a declaration.

cb = rise.plot.rcharts(DateRange=range, GridSize=[2 3]);
xregion(cb, forecastStart, forecastEnd);

cb + ["Output gap: ygap"
      "Inflation: 4*(p - p{-1})"
      "^Policy rate: r"];

plot(cb, db);

Each string is one chart. A caption may precede a colon. What follows is an expression evaluated against the data, not merely a field name, so transformations are written inline in the same lag notation a model file uses.

Where MATLAB already has a name for something, that name is used and the function carrying it is overloaded, so there is less to learn:

Call

What it does

cb + "Caption: expr"

adds a chart; append(cb, ...) is the same thing

plot(cb, db)

draws the charts

xline(cb, date), yline(cb, y)

add reference lines; asking twice draws once

xregion(cb, from, to)

adds a shaded span, one row per period

grid(cb, 'off')

turns the grid off

reset(cb)

empties the list and keeps every setting

isempty(cb)

true when nothing has been added

GridSize is [rows cols], spelled as a tiled layout spells it.

7.1. The four marks

Form

Meaning

Caption: expression

the caption is what precedes the colon

^expression

do not apply the chart-level transform to this chart

? inside an expression

one series per member of Variants, with a legend

-- alone

a page break; start a new figure here

A colon also appears inside expressions, in a range. The test is brackets: a candidate caption containing one is not a caption, so y(1:4) stays whole while \pi^e: p splits. Operator characters are allowed in a caption on purpose, because the interpreter is on by default and the captions worth writing use them.

7.2. Variants

A scenario, regime, model or vintage comparison is the case a loop over names handles worst. It is one line here:

cb.Variants = ["Output", "Output_low"];
cb + "Output, both scenarios: ?";

The placeholder is replaced by each member in turn, the resulting series share one chart, and the legend follows from the variant list.

Overlaid, or one tile each. Overlaying is right for two scenarios on one scale. It stops being readable once there are several, or once they differ enough in level that the interesting one is a flat line at the bottom. VariantLayout chooses:

cb.VariantLayout = "separate";

Each variant then gets its own tile, captioned with the subject above and the case below, and the legend is dropped as redundant. This is what a grammar of graphics calls faceting; the idea comes from there rather than from any macro-modelling toolbox. The split happens before pagination, so ChartsPerFigure and the page breaks count the tiles that actually get drawn.

7.3. Shading and reference lines

Shade is handed to RISE’s own shade, so it takes one row per period and more than one episode can be marked from a single declaration:

xregion(cb, forecastStart, forecastEnd);   % add one span
xregion(cb, rec2Start, rec2End);           % and another

cb.Shade = [rec1Start rec1End; rec2Start rec2End];  % or set them all

The shading sits behind the data and leaves the vertical limits alone. XLine and YLine hold vertical and horizontal reference lines, set directly or added with xline and yline. Asking for the same line twice draws it once, which matters because YLine already carries a line at zero. All three are converted to the axis’s own units, so a date lands where the calendar says rather than in the first century.

7.4. Specification and rendering are separate

resolve works the charts out against data and opens no figure:

spec = resolve(cb, db);

Each entry carries the resolved caption, the expression as written, the series, the legend, whether a person wrote the caption, whether the chart failed and why, and whether it is a page break. plot consumes exactly this and adds tiling, annotation, the named style and the date axis.

That seam is the point. Figures and a figure in a published report read the same structure, so the two cannot drift apart, and a further backend needs no change here.

7.5. When the range is applied

DateRange cuts the series down after the expression is evaluated and the transform applied. A backward-looking expression needs the observations before the window in order to produce the first point inside it; trimming the data first would quietly cost the opening period of every growth-rate chart.

The window is also clipped to what each series actually has. A chart written as a growth rate is one period shorter than the levels beside it, and asking such a series for the full window is an error.

7.6. A broken chart keeps its tile

The default is to carry on:

chart 2 (Ouput) failed: Unrecognized function or variable 'Ouput'.

The failure is reported by index and by the string as written, and the tile stays, marked. Dropping it would shift every chart after it up one place, which is how a reader ends up looking at the wrong series and believing it. Set OnError to "stop" to raise RISE:rcharts:badExpression instead.

7.7. Captions

Resolution order, in full: an explicit caption; then the series description when UseDescription is on; then the expression itself. Arithmetic does not carry a description, so a computed chart falls through to its formula, which is the right way round.

LineBreak splits a caption into lines, giving a subtitle. Interpreter chooses how the text is read and defaults to "tex", because the material is full of Greek letters and subscripts. A caption a person wrote passes through it untouched. A name the declaration generated is escaped first, so a variable called Output_low does not reach the page as Output with a subscript. The distinction is kept per line, which is what lets a faceted caption carry an authored subject above a generated variant name.

7.8. The named style

cb.Style = "rise";    % or "plain"

One place for color order, line width, grid weight, font size, shade color and rule color. A project sets it once and every figure follows; changing the name changes every figure with no other edit. An unknown name is refused by RISE:chartstyle:unknown, which lists the styles that exist. Adding a style means adding a case in rise.plot.chartstyle and nothing else.

7.9. Property summary

Group

Properties

data

DateRange, Transform, Decimals

captions

UseDescription, ShowExpression, LineBreak

variants

Variants, VariantMark, VariantLayout

layout

GridSize, ChartsPerFigure

annotation

Shade, XLine, YLine, Grid

style

Style, PlotFcn, Interpreter, and the pass-through buckets FigureOptions, AxesOptions, PlotOptions, TitleOptions

behavior

OnError

A property name that does not exist is refused by the constructor rather than becoming a new property.

Worked example: rise-modern-tutorials/Reporting/rcharts.