Symbol Labels and Notes - openmpp/openmpp.github.io GitHub Wiki

Home > Model Development Topics > Symbol Labels and Notes

This topic describes human-language labels and notes associated with model symbols. These labels and notes are used in a model's UI, documentation, and the IDE.

Related topics

Topic contents

Introduction and outline

This topic describes how to provide human-readable documentation for model symbols using labels and notes. Symbol labels and notes are used in the model's UI and in the model's generated Symbol Reference.

Labels and notes are described in separate subtopics. A final subtopic describes a family of options understood by the OpenM++ compiler which can help identify missing labels, notes, or translations.

[back to topic contents]

Symbol labels

This subtopic is organized into the following sections:

[back to topic contents]

Symbol labels: introduction

Labels for model symbols play an important role in the UI for a model, providing comprehensible human-language text for

  • parameters,
  • parameter dimensions,
  • enumerations (classifications, ranges, partitions),
  • enumerators of classifications,
  • tables,
  • table dimensions,
  • table expressions,
  • parameter groups (parameter hierarchy)
  • table groups (table hierarchy),
  • attributes.

Labels for model symbols are also used to aid a model developer using C++ symbols in an IDE. The OpenM++ compiler uses a model's labels to construct doxygen comments in generated C++ code, which can be used by an IDE to display contextual pop-ups for symbols in the model's C++ code, as described below.

See the subtopic identifying missing symbol documentation in this topic for functionality to help identify missing labels or translations. This can be helpful when publishing a model for external users.

A symbol label can also be used in the authored component of model documentation if that content uses GetLabel, as described here.

[back to symbol labels]
[back to topic contents]

Symbol labels: inline with declaration, e.g. //EN

Model symbols are declared in syntactic islands in model code. A model symbol can have a label for each human language declared in the languages statement. A symbol label can be provided where the symbol is declared using an in-line comment, for example

actor Person 
{
    //EN Union counter
    int unions = {0};	
...

To be recognized as a language label, there must be no white space between // and the language code, and some white space is required between the language code and the label text. OpenM++ silently ignores unrecognized language codes.

In this example, a label is provided for the symbol unions by a comment on the line immediately preceding the symbol declaration. It can also be provided on the same line as the declaration by placing the trailing // comment there.

Model code sometimes declares a symbol positionally rather than using a name. A label can be provided for a positionally-delcared symbol on the same line or on the immediately preceding line, just like for symbols with names.
For example the table declaration

table Person T01_LifeExpectancy //EN Life Expectancy
{
   {
      unit,           //EN Total simulated cases
      duration(),     //EN Total duration
      duration()/unit //EN Life expectancy decimals=3
   } //EN Quantities
};

provides a label for the table itself, for each of the the three expressions in the table, and for the expression dimension of the table, all in the EN language of the model.

Notice that the positional location of the table expression dimension is the trailing closing } of the expression dimension, after all expressions.

[back to symbol labels]
[back to topic contents]

Symbol labels: //LABEL

A symbol label can also be provided by a //LABEL comment in model code. This is particularly useful for models which support more than one language.

In the following example, the EN label for the SimulationCases parameter is provided where it is declared

parameters {
    //EN Number of cases in run (over all members)
    long long SimulationCases;
};

and the French language version of the label is provided elsewhere using //LABEL

//LABEL(SimulationCases,FR) Nombre de cas (dans tous les membres de l'execution)

To be recognized as a human-language label, there must be no white space between // and LABEL. Subsequent white space is optional. The arguments to //LABEL are the symbol name and the language code, which to be recognized must be one of those declared in the languages statement.

A label supplied inline with the symbol declaration in model code takes precedence over a label supplied through a //LABEL comment in model code.

OpenM++ silently ignores unrecognized symbol names and language codes in //LABEL comments.
Modgen-specific: Modgen treats a LABEL comment with an unrecognized symbol or language as an error. Note that OpenM++ has other mechanisms to help model devs identify missing or mistyped labels described here.

[back to symbol labels]
[back to topic contents]

Symbol labels: //LABEL with two-part name

The //LABEL syntax uses a two-part name to provide a label for the dimension of a parameter or table, for an expression of a table, for the expression dimension of a table, and for classification levels (enumerators).

The first part of a two-part name is the name of the parameter, table, or classification.
The second part of a two-part name denotes the dimension, expression, or enumerator.

The separator for a two-part name in a LABEL comment can be either :: or ..
Modgen-specific: Modgen recognizes only . as a separator in two-part names.

There are two ways to specify the second part of a two-part name:

  • the explicit short name, or
  • the Modgen naming scheme.

[back to symbol labels]
[back to topic contents]

Symbol labels: //LABEL with two-part name (explicit short name)

In the following example, the dimensions and expressions of the table TotalPopulationByYear have been given explicit short names:

table Person TotalPopulationByYear //EN Life table
{
   //EN Curtate age
   age => integer_age +
   *
   {
      pop => unit,   //EN Population start of year
      py => duration() //EN Average population in year
   } //EN Quantity
};

The following //LABEL statements provide a French language label for the table dimensions and expressions using their explicit short names age, pop, and py:

//LABEL(TotalPopulationByYear.age,FR) Âge intègre
//LABEL(TotalPopulationByYear.pop,FR) Population au début de l'année
//LABEL(TotalPopulationByYear.py,FR) Population moyenne pendant l'année

The expression dimension of a table is a special case. It uses the fixed name expression_dimension as the second part of the two-part name.

Continuing the above example, a French version of the expression dimension of the table is supplied by

//LABEL(T01_LifeExpectancy.expression_dimension,FR) Quantité

This string is displayed in the UI in the header of the table's expressions.

Here's another example showing //LABEL comments with explicit short names to provide French versions for the dimensions of the parameter UnionDurationBaseline in RiskPaths:

   double UnionDurationBaseline
      union_order => [UNION_ORDER]      //EN Union order
      union_dur   => [UNION_DURATION];  //EN Union duration
   //LABEL(UnionDurationBaseline.union_order,FR) Ordre d'union
   //LABEL(UnionDurationBaseline.union_dur,FR) Durée d'union

Here's an example showing //LABEL comments with explicit short names to provide the translation for the levels (enumerators) of the classification UnionDurationBaseline in RiskPaths:

classification UNION_ORDER 		//EN Union order
{
   first => UO_FIRST,  //EN First union 				
   second => UO_SECOND //EN Second union 				
};
//LABEL(UNION_ORDER.first,FR) Première
//LABEL(UNION_ORDER.second,FR) Deuxième

[back to symbol labels]
[back to topic contents]

Symbol labels: //LABEL with two-part name (Modgen scheme)

The other method to specify the second part of a two-part name in a //LABEL comment uses the naming scheme used in Modgen for //LABEL.

In the Modgen naming scheme, a LABEL comment for a parameter dimension has the form
//LABEL(ParameterName.DimN,LANG) text
where N is {0,1,...,rank-1}, rank is the number of parameter dimensions, LANG is the language code, and text is the label.

and a LABEL comment for a table dimension has the form
//LABEL(TableName.DimN,LANG) text
where N is {0,1,...,rank}, rank is the number of classificatory dimensions in the table, LANG is the language code, and text is the label.
NB: The naming scheme for table dimensions differs from that used for default short names. Unlike a default short name, it includes the expression dimension of the table in the numbering.

In the Modgen naming scheme, a LABEL comment for a table expression has the form
//LABEL(TableName.ExprN,LANG) text
where N is {0,1,...,expressions}, expressions is the number of expressions in the table, LANG is the language code, and text is the label.

Here's the version of the French translation for the labels of the previous example using the Modgen naming scheme:

//LABEL(TotalPopulationByYear.Dim0,FR) Âge intègre
//LABEL(TotalPopulationByYear.Expr0,FR) Nombre total de cas simulés
//LABEL(TotalPopulationByYear.Expr1,FR) Durée totale
//LABEL(TotalPopulationByYear.Expr2,FR) Espérance de vie

[back to symbol labels]
[back to topic contents]

Symbol labels: LABEL text file

A symbol label can be supplied as a .txt file in the doc sub-directory of the model. For example, the file RiskPaths/doc/LABEL.ProbMort.FR.txt provides a French language version of the label of the ProbMort parameter. The file contents is a single line, which in this example is

Probabilités de décès

To be recognized as a LABEL text file, the filename must be named as in the example: LABEL, followed by the symbol name, followed by the code of a model language, followed by txt, with these parts separated by the . character.

If both //LABEL and a LABEL text file are present, the LABEL text file takes precedence.

A label supplied inline with the symbol declaration in model code takes precedence over a label supplied through a LABEL text file.

[back to symbol labels]
[back to topic contents]

Symbol notes

A model symbol can have an associated descriptive note. The note for a published symbol such as a parameter, table, or classification can be viewed in the UI in context by clicking the information icon. A symbol note may also be incorporated into Generated Model Documentation in the model's Symbol Reference.

The content of a note can be provided in one of two ways: through a /*NOTE comment in model code, or through a .md markdown file in the doc sub-directory of the model.

Model notes are authored using markdown, with some augmentations and limitations, as described in writing content.

This subtopic is organized into the following sections:

[back to topic contents]

Symbol notes: /*NOTE in model code

The text for a note can be given in model code using a NOTE comment, For example, in RiskPaths,

/*NOTE(Person.FirstPregEvent, EN)
    The first pregnancy event. This is the main event of analysis and
    censors all future union events.
*/

in the Fertility.mpp model code module provides a note in the human language EN for the event FirstPregEvent in the Person entity.

The rules for two-part symbol names in NOTE comments are the same as those for //LABEL given in symbol labels.

To be recognized as a human-language note, there must be no white space between /* and NOTE. Subsequent white space is optional.

[back to symbol notes]
[back to topic contents]

Symbol notes: NOTE markdown file

A symbol note can be supplied as a .md markdown file in the doc sub-directory of the model. For example, the file RiskPaths/doc/NOTE.ProbMort.EN.md provides the English language version of the descriptive note for the ProbMort parameter.

The file content uses the markdown syntax, which for NOTE.ProbMort.EN.md is:

* The values in `ProbMort` have no effect if [`CanDie`](#CanDie) is `false`.
* The [GetLabel(Person::DeathEvent)](#DeathEvent) function in `RiskPaths`
 treats the values in `ProbMort` as though they are hazards.
 Arguably, the annual probabilities of death in `ProbMort` should be converted to hazards
 using the formula 
    \(h_{x}=-\ln(1-q_{x})\).
 where 
 \(h_{x}\) is the hazard of death and \(q_{x}\) is the annual mortality rate.

and, depending on browser capabilities and environment, might render like this in the RiskPaths Symbol Reference, towards the top of the topic, after the hierarchy and before the dimensions table:

ProbMort in RiskPaths Symbol Reference

See writing content for more information about note content and rendering.

[back to symbol notes]
[back to topic contents]

Symbol notes: The special model symbol

A note provided for the special symbol model will be displayed as introductory text in the model UI and in the model's generated Symbol Reference.

For example, the Info.mpp module in the OzProj model provides the following note for the model symbol:

/*NOTE(model, EN)
  A series of OzProj model versions accompany the on-line course "Practical Microsimulation".
  That course presents how to use Modgen to construct a microsimulation model
  to produce detailed demographic projections from a large heterogenous microdata population.

  The course content also teaches how to use Modgen through concrete self-contained examples.

  The model is based on data from the web site of the Australian Bureau of Statistics.
*/

Clicking the information icon for the OzProj model in the UI displays a pop-up like

Model Information for OzProj

If provided, the note for the model symbol is incorporated into the model's Symbol Reference, but this can be disabled using the symref_model_symbol option, as described in customizing the symbol reference. If the model has autonomous authored documentation with a home page, a note for the model symbol might be redundant in model documentation.

[back to symbol notes]
[back to topic contents]

Symbol notes: Modgen formatting indicators

Modgen formatting indicators in notes are described in the Modgen Developer’s Guide in section “Formatting of symbol notes” on page 217. By default, the OpenM++ compiler identifies and converts Modgen formatting indicators to equivalent markdown when it encounters a note in model code in /*NOTE.

If a model uses markdown exclusively in notes in model code, this conversion can be disabled using the following statement:

options convert_modgen_note_syntax = off;

In practice, markdown and Modgen formatting indicators can co-exist in a /*NOTE comment without interfering.

Modgen formatting indicators are ignored and not converted in NOTE markdown files.

[back to symbol notes]
[back to topic contents]

Identifying missing symbol documentation

A common issue for model developers is to identify undocumented symbols, and, once identified, insert the missing documentation in the model source code.

The OpenM++ compiler supports a family of options to aid that process. Each member of the family targets a specific kind of missing documentation. When an option is set to on, the compiler will generate a warning for each occurrence of missing documentation of that kind. The warning includes the model code file and line where the symbol was declared, except for missing translation warnings which instead give the location of the untranslated text. In an IDE like Visual Studio, double-clicking on the warning in the log window navigates immediately to that model source code location in the IDE editor.

By default these options are off. Multiple options can be turned on at the same time.

Here's an example to identify all published parameters in RiskPaths which have no descriptive note in the model's default language. Inserting the following line in ompp_framework.ompp

options missing_note_warning_published_parameter = on;

causes the compiler to emit warnings like:

1>../code/Unions.mpp(39): warning : missing note for published parameter 'AgeBaselineForm1'
1>../code/Fertility.mpp(21): warning : missing note for published parameter 'AgeBaselinePreg1'
1>../code/Mortality.mpp(25): warning : missing note for published parameter 'CanDie'
1>../code/Mortality.mpp(26): warning : missing note for published parameter 'ProbMort'
1>../code/Unions.mpp(45): warning : missing note for published parameter 'SeparationDurationBaseline'
1>../code/Unions.mpp(42): warning : missing note for published parameter 'UnionDurationBaseline'
1>../code/Fertility.mpp(24): warning : missing note for published parameter 'UnionStatusPreg1'

Here's an example which identifies all published symbols in IDMM which have a descriptive label or note in the default language, but whose translation is missing in one of the model's other languages. The source of IDMM was changed for this example to deliberately create missing translations.

Inserting the following lines in ompp_framework.ompp

options missing_translated_label_warning_published_any = on;
options missing_translated_note_warning_published_any = on;

causes the compiler to emit warnings like:

1>../code/HostCore.mpp(89): warning : missing 'FR' translated label for published symbol 'event_count'
1>../code/HostCore.mpp(82): warning : missing 'FR' translated note for published symbol 'NumberOfHosts'

For missing translation warnings, the warning code location is the location of the label or note in the default language, not the location of the symbol declaration. That's so the warning can be used to navigate to the text to be translated.

The missing translated note warning above gave the code location HostCore.mpp(82).
Here's an extract of the code starting at that location (line 82):

/*NOTE(NumberOfHosts,EN)
This number does not change during the simulation
because there are no births, immigration, or deaths.
*/

Double-clicking the warning in an IDE navigates directly to that NOTE in the IDE editor. The associated parameter NumberOfHosts is declared elsewhere.

The following table lists the available options to emit warnings for missing symbol documentation, grouped by category. The Scope column shows what produces a warning for the given option. For example, the missing_label_parameter option produces a warning for a missing label for a parameter or for a parameter group. It does not produce a missing label warning for a parameter dimension. That's because the default label for a parameter dimension is copied from the label of the enumeration for the dimension, and is usually sufficient. The scope of each option is deliberately restricted to produce useful actionable warnings.

Option Scope
Labels
  missing_label_warning_enumeration classification, classification level, range, partition
  missing_label_warning_parameter parameter, parameter group
  missing_label_warning_table table, table expression, table group
  missing_label_warning_attribute attribute
Labels - Published
  missing_label_warning_published_enumeration as above, but only if published
  missing_label_warning_published_parameter as above, but only if published
  missing_label_warning_published_table as above, but only if published
  missing_label_warning_published_attribute as above, but only if published
Notes - Published
  missing_note_warning_published_parameter published parameter
  missing_note_warning_published_table published table
  missing_note_warning_published_attribute published attribute
Translated Labels and Notes
  missing_translated_label_warning_any any symbol with an explicit label provided in the model's default language
  missing_translated_note_warning_any any symbol with a note provided in the model's default language
Translated Labels and Notes - Published
  missing_translated_label_warning_published_any as above, but only for published symbols
  missing_translated_note_warning_published_any as above, but only for published symbols

[back to topic contents]

⚠️ **GitHub.com Fallback** ⚠️