Skip to content

Commit eb905eb

Browse files
author
Alex Bikeyev
committed
docs: add dimensions reference with channel semantics, sequential vs set types, and COLORMAP function
Add comprehensive dimensions.md reference covering dimension declaration, set vs seq types, channel system with @.value/@.fill/@.font_color, and dimensional item references. Expand formatting.md with rule-driven formatting section, conditional formatting examples, and COLORMAP function for gradient-based color maps. Add dimensions.md as first entry in Reference navigation.
1 parent 94d7e4c commit eb905eb

3 files changed

Lines changed: 301 additions & 10 deletions

File tree

‎docs/reference/dimensions.md‎

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Dimensions reference
2+
3+
A dimension is a named axis of items used by one or more cubes. Dimension items
4+
are stable semantic labels, not grid coordinates. They are declared once and
5+
reused across cubes so the same terminology applies everywhere in a model.
6+
7+
## Declaration
8+
9+
Dimensions are declared with the `dim` command:
10+
11+
```openm
12+
dim Region North South East West
13+
dim Year --seq 2026 2027 2028 2029 2030
14+
dim Scenario Actual Base Upside Downside
15+
```
16+
17+
A dimension declaration has the form:
18+
19+
```text
20+
dim <name> [--set | --seq] <item1> <item2> ... <itemN>
21+
```
22+
23+
- `name` — the dimension identifier. Use `PascalCase` or descriptive names.
24+
- `--set` — explicit unordered set. This is the default when no flag is given.
25+
- `--seq` — ordered sequence. Item order matters for navigation, indexing, and
26+
sequential references.
27+
- Items are separated by whitespace. Multi-word items must be quoted.
28+
29+
### Sequential ranges
30+
31+
For `seq` dimensions, a range expression `start..end` expands to a consecutive
32+
sequence of intermediary items in rules. This is useful for time and index dimensions.
33+
34+
Ranges are only valid on `seq` dimensions. The engine expands the range into a
35+
sequence of items at declaration time, so the resulting items behave exactly like
36+
explicitly listed items.
37+
38+
## Dimension types
39+
40+
### `set` — unordered set
41+
42+
```openm
43+
dim Region North South East West
44+
```
45+
46+
A `set` dimension stores its items as an unordered collection. The order in which
47+
items are listed in the declaration is preserved for display purposes, but the
48+
engine does not treat it as meaningful for calculations. Items are accessed by
49+
name, not by position.
50+
51+
Use `set` for dimensions where items are categories without natural ordering:
52+
53+
- `Region`
54+
- `Department`
55+
- `Scenario`
56+
- `Product`
57+
58+
### `seq` — ordered sequence
59+
60+
```openm
61+
dim Month --seq Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
62+
```
63+
64+
A `seq` dimension is an ordered sequence. Item order is part of the dimension's
65+
semantics. Ordering enables sequential accessors and affects iteration, display,
66+
and recurrence rules.
67+
68+
Use `seq` for dimensions with natural ordering, especially time:
69+
70+
- `Month`, `Quarter`, `Year`
71+
- `Version` when versions follow a progression
72+
- `PlantAge` when age stages follow a sequence
73+
74+
### Why the distinction matters
75+
76+
Sequential references only resolve correctly on `seq` dimensions:
77+
78+
```openm
79+
dim Year --seq 2026 2027 2028 2029 2030
80+
81+
rule Cash::Cash.EndingCash:Year.2027 = Cash::[Cash.EndingCash:Year.PREV] + Cash::[Cash.FreeCashFlow:Year.THIS]
82+
```
83+
84+
If `Year` were declared as a `set`, `Year.PREV` and `Year.NEXT` would produce
85+
`#REF!` because the engine cannot determine the previous or next item without an
86+
explicit order.
87+
88+
The same applies to `FIRST`, `LAST`, and `THIS`:
89+
90+
```openm
91+
dim Month --seq Jan Feb Mar
92+
93+
rule PL::PLLine.Revenue:Month.Feb = PL::[PLLine.Revenue:Month.PREV] * 1.10
94+
rule PL::PLLine.Revenue:Month.Jan = PL::[PLLine.Revenue:Month.FIRST]
95+
```
96+
97+
## Channels and the `@` sigil
98+
99+
Every cell in a cube stores values in named channels. The `@` sigil introduces a
100+
channel selector in a rule address.
101+
102+
### Default value channel
103+
104+
The default channel is `@.value`. It is implied when no channel is written:
105+
106+
```openm
107+
# These two rules are equivalent
108+
rule Sales::Month.Jan = 1000
109+
rule Sales::@.value:Month.Jan = 1000
110+
```
111+
112+
### Style and format channels
113+
114+
Style and formatting rules target non-value channels:
115+
116+
```openm
117+
rule PL::@.fill:PLLine.Revenue:Year.2026 = #3B82F6
118+
rule PL::@.font_color:PLLine.Revenue:Year.2026 = #FFFFFF
119+
rule PL::@.font_weight:PLLine.Revenue:Year.2026 = 700
120+
rule PL::@.format_number:PLLine.Revenue:Year.2026 = 'preset:number(decimals=2; group=true)'
121+
```
122+
123+
Common channels include:
124+
125+
| Channel | Purpose |
126+
| --- | --- |
127+
| `@.value` | Default data channel |
128+
| `@.fill` | Background color |
129+
| `@.font_color` | Text color |
130+
| `@.font_weight` | Text weight, e.g. `700` for bold |
131+
| `@.font_italic` | Italic flag |
132+
| `@.font_size` | Text size |
133+
| `@.format_number` | Number or currency display format |
134+
| `@.text_h_align` | Horizontal alignment |
135+
| `@.text_v_align` | Vertical alignment |
136+
| `@.border_*` | Border style and color |
137+
138+
### Strict and shorthand forms
139+
140+
A full rule address includes the channel explicitly:
141+
142+
```text
143+
Cube::@.channel:Dim1.Item1:Dim2.Item2
144+
```
145+
146+
Most value rules omit the channel for readability:
147+
148+
```text
149+
Cube::Dim1.Item1:Dim2.Item2
150+
```
151+
152+
When the channel is omitted, `@.value` is assumed. Style and format rules must
153+
always include the channel.
154+
155+
### Channel references on the RHS
156+
157+
The `@` sigil is only needed when writing a rule that targets a non-value
158+
channel. RHS references to other cells use the same channel as the target unless
159+
explicitly overridden. For example, a rule on `@.fill` reads the `@.fill` channel
160+
of the referenced cell:
161+
162+
```openm
163+
rule Summary::@.fill:Plant.Apple = Inventory::@.fill:[PlantData.Status]
164+
```
165+
166+
A value-rule reference reads the value channel by default:
167+
168+
```openm
169+
rule PL::PLLine.GrossProfit:Year.2026 = PL::[PLLine.Revenue] - PL::[PLLine.COGS]
170+
```
171+
172+
## Dimension item references
173+
174+
Items are referenced by `DimensionName.ItemName`:
175+
176+
```openm
177+
rule PL::PLLine.Revenue:Year.2026 = 100000
178+
```
179+
180+
Use brackets for shorthand references when the item name contains spaces or
181+
special characters, or when using positional accessors:
182+
183+
```openm
184+
rule PL::PLLine.Revenue:Year.2026 = PL::[PLLine.COGS] * 2.0
185+
rule PL::PLLine.Revenue:Year.2027 = PL::[PLLine.Revenue:Year.PREV] * 1.10
186+
```
187+
188+
## Best practices
189+
190+
- Declare time dimensions with `--seq` so `[PREV]`, `[NEXT]`, `[FIRST]`, and
191+
`[LAST]` work.
192+
- Use `set` for categorical dimensions. Avoid implying order that does not exist.
193+
- Keep dimension item names stable. Changing an item name may (still) break rules
194+
that reference it. If this happens, update the rules to use the new item name.
195+
- Omit `@.value` in value rules for readability, but always include the channel
196+
in style and format rules.
197+
- Use descriptive dimension names. Short names like `A` and `B` are acceptable
198+
only for syntax examples, not production models.
199+
200+
## See also
201+
202+
- [Concepts: Dimensions](../concepts/dimensions.md)
203+
- [Rule syntax](rule-syntax.md)
204+
- [Scripting reference](scripting.md)

‎docs/reference/formatting.md‎

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,55 @@
11
# Formatting patterns
22

3-
OM Core uses number and currency formatting patterns based on the Unicode Common Locale Data Repository (CLDR). This page explains the origin of the syntax and the pattern types OM Core supports.
3+
OM Core uses number and currency formatting patterns based on the Unicode Common
4+
Locale Data Repository (CLDR). This page explains the origin of the syntax and
5+
the pattern types OM Core supports.
46

5-
This page is about **number and currency display patterns**, not visual styles such as font color or background fill. Visual styles are set through channels like `@.fill` and `@.font_color`. See the [Scripting reference](scripting.md) for how to use style channels.
7+
This page is about **number and currency display patterns**, not visual styles such
8+
as font color or background fill. Visual styles are set through channels like
9+
`@.fill` and `@.font_color`. See the [Scripting reference](scripting.md) for how
10+
to use style channels.
11+
12+
## Rule-driven formatting
13+
14+
All formatting in OM Core is rule-driven. A format string is attached to a cell
15+
or slice through the `@.format_number` channel using the same `rule` syntax as
16+
value rules:
17+
18+
```openm
19+
rule PL::@.format_number:Account.Revenue:Year.2026 = '#,##0.00'
20+
```
21+
22+
You can also set a hard value directly through the UI or REPL, but under the hood
23+
the engine still stores it as a rule on the format channel. Because formatting
24+
is a rule, it can reference other cells, use wildcards, and respond to the same
25+
dimensional context as any other rule.
26+
27+
## Conditional formatting
28+
29+
Because formatting is rule-driven, it can be conditional. A rule on `@.fill`,
30+
`@.font_color`, or `@.font_weight` can depend on the value of the same cell or
31+
other cells:
32+
33+
```openm
34+
rule Checks::@.fill:Check.Variance:Month.*:Department.* =
35+
if(abs(Variance::[VarianceLine.Variance]) > 1000, "#FFCCCC", "#FFFFFF")
36+
37+
rule PL::@.font_color:Account.EBITDA:Year.*:Scenario.* =
38+
if(PL::[Account.EBITDA] < 0, "#FF0000", "#000000")
39+
```
40+
41+
The format or style is recomputed automatically when the underlying values change,
42+
so the visual presentation always stays consistent with the model state.
643

744
## Source
845

946
The formatting syntax in OM Core originates from CLDR number and currency patterns:
1047

1148
[Number and currency patterns — CLDR](https://cldr.unicode.org/translation/number-currency-formats/number-and-currency-patterns)
1249

13-
CLDR defines locale-aware patterns for presenting numbers, currencies, percentages, and compact numbers. OM Core uses these patterns as the basis for formatting values in views.
50+
CLDR defines locale-aware patterns for presenting numbers, currencies,
51+
percentages, and compact numbers. OM Core uses these patterns as the basis for
52+
formatting values in views.
1453

1554
## Pattern types
1655

@@ -23,7 +62,9 @@ CLDR supports four general-purpose number patterns:
2362

2463
## Pattern characters
2564

26-
In CLDR patterns, characters such as `.` and `,` are placeholders. The actual decimal and grouping symbols are determined by the active locale. Literal characters that are not placeholders must be quoted.
65+
In CLDR patterns, characters such as `.` and `,` are placeholders. The actual
66+
decimal and grouping symbols are determined by the active locale. Literal
67+
characters that are not placeholders must be quoted.
2768

2869
Common pattern characters:
2970

@@ -47,28 +88,36 @@ CLDR currency patterns may include:
4788

4889
## Compact numbers
4990

50-
CLDR also defines compact patterns for values like `1M` or `1 million`. These patterns vary significantly by language and may include plural categories.
91+
CLDR also defines compact patterns for values like `1M` or `1 million`. These
92+
patterns vary significantly by language and may include plural categories.
5193

5294
## OM Core usage
5395

54-
When you set a format string in OM Core, you can write either a CLDR-style pattern or an OM Core preset expression.
96+
When you set a format string in OM Core, you can write either a CLDR-style
97+
pattern or an OM Core preset expression.
5598

5699
### CLDR-style patterns
57100

58-
A CLDR-style pattern is a locale-aware pattern resolved against the cell or cube locale:
101+
A CLDR-style pattern is a locale-aware pattern resolved against the cell or cube
102+
locale:
59103

60104
```openm
61105
rule PL::@.format_number:Account.*:Year.*:Scenario.* = "#,##0.00"
62106
```
63107

64-
This means the same model can be displayed correctly across different locales without changing the underlying data.
108+
This means the same model can be displayed correctly across different locales
109+
without changing the underlying data.
65110

66111
### OM Core preset expressions
67112

68-
A preset expression is a higher-level, readable directive that the engine maps to a concrete format. Presets are useful when you want explicit control over decimals, grouping, negative numbers, and zero display without writing a raw CLDR pattern:
113+
A preset expression is a higher-level, readable directive that the engine maps to
114+
a concrete format. Presets are useful when you want explicit control over
115+
decimals, grouping, negative numbers, and zero display without writing a raw CLDR
116+
pattern:
69117

70118
```openm
71-
rule PL::@.format_number:Account.*:Year.*:Scenario.* = 'preset:number(decimals=2; group=true; negative=parentheses; zero=dash)'
119+
rule PL::@.format_number:Account.*:Year.*:Scenario.* =
120+
'preset:number(decimals=2; group=true; negative=parentheses; zero=dash)'
72121
```
73122

74123
Common preset parameters include:
@@ -80,6 +129,43 @@ Common preset parameters include:
80129
| `negative` | Negative number style, e.g. `parentheses` |
81130
| `zero` | Zero display, e.g. `dash` |
82131

132+
## Color maps
133+
134+
OM Core supports color map functions for conditional color formatting. A color map
135+
maps a numeric value to a color along a named gradient.
136+
137+
### Syntax
138+
139+
```text
140+
COLORMAP("name", [min; max])
141+
```
142+
143+
- `name` — the color map name, e.g. `"viridis"` or `"plasma"`.
144+
- `[min; max]` — the value range to map to the gradient.
145+
146+
The function returns a color for the current cell value by interpolating it
147+
between `min` and `max` across the named gradient.
148+
149+
### Examples
150+
151+
Use `COLORMAP` on the `@.fill` or `@.font_color` channel:
152+
153+
```openm
154+
rule PL::@.fill:Account.EBITDA:Year.*:Scenario.* =
155+
COLORMAP("viridis", [0; 100000])
156+
157+
rule Variance::@.fill:VarianceLine.VariancePct:Account.*:Month.* =
158+
COLORMAP("plasma", [-0.5; 0.5])
159+
```
160+
161+
In the first example, an EBITDA value of `0` maps to one end of the Viridis
162+
gradient and `100000` maps to the other end. Values in between receive an
163+
interpolated color. In the second example, negative and positive variance
164+
percentages are shown on opposite ends of the Plasma gradient.
165+
166+
Color maps are useful for heatmaps, variance highlighting, and any visual
167+
formatting that should scale continuously with a numeric value.
168+
83169
For the full CLDR specification, see:
84170

85171
[Number and currency patterns — CLDR](https://cldr.unicode.org/translation/number-currency-formats/number-and-currency-patterns)

‎mkdocs.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ nav:
5858
- Interface overview: ui-ux/interface.md
5959
- TUI: ui-ux/tui.md
6060
- 📖 Reference:
61+
- Dimensions: reference/dimensions.md
6162
- Rule syntax: reference/rule-syntax.md
6263
- Scripting: reference/scripting.md
6364
- Formatting: reference/formatting.md

0 commit comments

Comments
 (0)