Printing timeseries

<< Click to Display Table of Contents >>

Navigation:  Details >

Printing timeseries

Previous pageReturn to chapter overviewNext page

For the time being, the explanation regarding print labels is a bit rudimentary. But the following illustrates the main points.

Printing of timeseries is a quite complicated topic, especially if mixing frequencies, or using name-composition or array-series. But the most complicated part is dealing with labels on the timeseries, for instance if printing x{%i}, where the {%i} part should be shown as letters/digits. In the following, we will assume that %i = 'a', which will entail that the variable should be printed with the label xa instead of the hard-to-understand x{%i}.

time 2001 2003;
xa = 2;
%= 'a';
prt x{%i};
 
//                  xa         % 
// 2001         2.0000         M 
// 2002         2.0000      0.00 
// 2003         2.0000      0.00 

 

To to this, info from the parser is needed. For example, in the parser grammar file, Cmd3.g, a name part like {%i} emits an ASTCURLY token of the following kind:

^({token("ASTCURLY¤"+($expression.text)+"¤"+($expression.start)+"¤"+($expression.stop), ASTCURLY, 0)} expression)

 

For instance, in this case the following AST node is emitted:

ASTCURLY¤%¨i¤[@5,5:5='%',<1355>,1:5]¤[@7,7:7='i',<1387>,1:7]

 

This contains the .text part (i), the .start part ([@5,5:5='%',<1355>,1:5]), and the .stop part ([@7,7:7='i',<1387>,1:7]). When walking the AST tree, the .text/.start/.end parts are extracted (by splitting at the ¤ character), and the node is transformed into a more normal-looking ASTCURLY node, while retaining the information. This node will contain the information in the field .specialExpressionAndLabelInfo, which in this case would contain the three strings i, [@5,5:5='%',<1355>,1:5], and [@7,7:7='i',<1387>,1:7]. The two last strings are ANTLR's way of depicting start/stop info, which is a bit cryptic. But the essence is that the last parts of the string (1:5 and 1:7) tells us that the string i starts in line 1, position 5 and ends in line 1, position 7.

When the AST tree is walked later on, this ANTLR info is transformed into the following C# code:

O.ReportLabel(

  smpl, 

  O.Lookup(smpl, null, null, "%i", null, null, new  LookupSettings(), EVariableType.Var, null), 

  "%¨i|[@5,7:7='%',<1359>,1:7]|[@7,9:9='i',<1391>,1:9]"

)

 

ReportLabel() uses smpl (the object containing the sample period and other things), the variable (IVariable) corresponding to %i, and the string "%¨i|[@5,7:7='%',<1359>,1:7]|[@7,9:9='i',<1391>,1:9]". The smpl object has a field .labelRecordedPieces (which is a List<RecordedPieces>), where the info is added. The line with the string is similar to the ANTLR raw output, only | are used for separation, and the start/stop is enclosed in []-brackets.

The statement prt x{%i}; will contain the following code:

ope0.variable[bankNumber] = 

O.Lookup(

  smpl, 

  null, 

  (new ScalarString("x")).Concat(smpl, O.ReportLabel(smpl, O.Lookup(smpl, null, null, "%i", null, null, 

     new  LookupSettings(), EVariableType.Var, null), "%¨i|[@5,7:7='%',<1359>,1:7]|[@7,9:9='i',<1391>,1:9]")), 

  null, 

  new LookupSettings(), 

  EVariableType.Var,

  null

);

 

The left-hand side ope0.variable[bankNumber]  assigns the right-hand side to an object that can be used for printing. The interesting line is the line that starts with (new ScalarString("x")).Concat(.... So O.Lookup() accepts an IVariable as its third argument, where this IVariable will be a ScalarString containing the string xa. (the a because the O.Lookup() in that line looks up %i, which returns the string 'a', and .Concat() concatenates the two string 'x' and 'a').

The string "%¨i|[@5,7:7='%',<1359>,1:7]|[@7,9:9='i',<1391>,1:9]" contains three parts:

i

[@5,7:7='%',<1359>,1:7]

[@7,9:9='i',<1391>,1:9]

 

The first part tells us that we are replacing i from the label (which looks like x¨{%¨i} due to the parser glue symbols), and that this i is found from line 1 position 7 to line 1 position 9.

The method OPrintLabels() in Print.cs handles this, trying to in-substitute the %i part of the label x{%i} with the value that %i actually has (namely the string 'a'). This results in x{'a'}, which is then abbreviated to xa.

The above methodology also works for expressions like prt x{#i}, where #i can be a list of strings. Consider this:

time 2001 2003;
xa = 2; xb = 3; xc = 4;
#= a, b, c;
prt <n> x{#i};
 
//                  xa             xb             xc 
// 2001         2.0000         3.0000         4.0000 
// 2002         2.0000         3.0000         4.0000 
// 2003         2.0000         3.0000         4.0000 

 

The same functionality also works for array-series indexes, like the following:

time 2001 2003;
= series(1);
x[a] = 2; x[b] = 3; x[c] = 4;
#= a, b, c;
prt <n> x[#i];
 
//                x[a]           x[b]           x[c] 
// 2001         2.0000         3.0000         4.0000 
// 2002         2.0000         3.0000         4.0000 
// 2003         2.0000         3.0000         4.0000 

 

When lists are used in x{#i} and x[#i], some more complicated looping occurs in OPrintLabels(), and the labels are put into different print columns. But the basic ideas are the same.

At an earlier point, instead of using the parser to tell us where the relevant strings were located, it was tried to just decipher a label like x{%i} more directly, just looking for curlies {} and brackets [], and trying to understand the inside of these. But this did not work properly, among other things because the inside of {} or [] can be arbitrarily complicated, and not necessarily something easy like %i. Therefore we use ANTLR to spit out this info, which is much more robust.

Another complication is when printing for instance with print-codes like prt <n d p> x{%i};. In that case, several print columns are created, one for n, one for d, and one for p operator. When using a list like prt <n d p> x{#i};, a kind of label pairing takes place, because if #i contains three strings, this PRT prints out 3*3 = 9 columns.