Template chunk key encoding
A flexible chunk key encoding inspired by rust/ python format string templates.
Template string syntax
Templates are strings including braced {} expressions denoting where to insert values. Literal braces MAY be escaped by doubling them, e.g. {{.
The expression consists of one of
- a positive integer representing a zero-based index into the chunk coordinate
- a negative integer representing an index from the end of the chunk coordinate, where
-1is the last value; i.e.positive_index = len(chunk_coordinate) + negative_index - an asterisk
*representing a all values of the chunk coordinate not represented elsewhere
Optionally, this MAY be followed by a colon, then a 0, then the minimum width of the resulting inserted string, to be left-padded by zeros.
{0}denotes the first value of the chunk coordinate, in decimal format{-1}denotes the last value of the chunk coordinate, in decimal format{*}is a catch-all/ rest operator:- If
{*}is present, the configuration object MUST include theseparatorfield - No more than one
*term may be present - Values of the chunk coordinate not included explicitly by another expression are included in left-to-right order, separated by the value of the
separatorfield
- If
{1:05}denotes the second value of the chunk coordinate, in decimal format, left-padded with zeros until it is 5 digits long- If the coordinate value's decimal representation is already 5 or more digits long, ignore the padding term
Outside of braces, the template string:
- MUST NOT begin with
/, but MAY contain it elsewhere - MUST NOT contain the substrings
..,\,\0, or// - MUST NOT contain the substring
zarr.json
The template string MUST contain at least one braced template expression.
Grammar
The template string syntax can be described by the following BNF grammar. For brevity, only the characters recommended by the Zarr specification are considered for literals, but implementations SHOULD implement full unicode support.
Note that the grammar describes the syntactic structure only; the additional lexical constraints listed above (e.g. MUST NOT begin with /, MUST NOT contain .., \, \0, //, or zarr.json) and the validation rules below still apply.
<template> ::= <element> | <element> <template>
<element> ::= <expression> | <escaped-brace> | <literal-char>
<expression> ::= "{" <index> "}" | "{" <index> ":" <padding> "}"
<padding> ::= "0" <positive>
<index> ::= "*" | <integer>
<integer> ::= "0" | <positive> | "-" <positive>
<positive> ::= <nonzero> | <nonzero> <positive>
<escaped-brace> ::= "{{" | "}}"
<literal-char> ::= <letter> | <digit> | "-" | "_" | "."
<letter> ::= "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j"
| "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t"
| "u" | "v" | "w" | "x" | "y" | "z"
| "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J"
| "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T"
| "U" | "V" | "W" | "X" | "Y" | "Z"
<digit> ::= "0" | <nonzero>
<nonzero> ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"Regular expression
Template expressions match the regular expression
\{((\*|-?\d+)(:0(\d+))?)\}For each term, the matched groups are
- 1: the whole term within the braces
- 2: the index or asterisk
- 3: the whole formatting configuration
- 4: the number of digits to left-pad the value up to
Note that this regular expression does not support escaped braces.
Serialisation
Object: Template Chunk Key Encoding
| field | requirement level | type | description |
|---|---|---|---|
| name | MUST | literal string "template" | |
| configuration | MUST | Configuration |
Object: Template Chunk Key Encoding Configuration
| field | requirement level | type | description |
|---|---|---|---|
| template | MUST | string | Format string to be interpolated |
| separator | MAY | string | MUST be included if the template string includes the catch-all pattern {*} |
Validation
A given template string may be valid only for a particular set of chunk coordinate lengths (array dimensionalities). Providing an incongruent chunk coordinate and template string MUST result in an error. Examples include
- The chunk coordinate length does not equal the number of template expressions, where there is no catch-all expression
{*} - The catch-all expression would be populated by 0 coordinate values
- A positive index is after the end of the coordinate
- A negative index is before the start of the coordinate
- Two indices, positive or negative, resolve to the same value in the chunk coordinate
Examples
{
"name": "template",
"configuration": {
"format": "images/{-1}/{*:04}.jpeg",
"separator": "_"
}
}{
"name": "template",
"configuration": {
"format": "{2}-{0}_{1}"
}
}See examples.tsv for a set of examples/ test cases.
Motivation
This chunk key encoding covers the use cases for the proposed prefix and suffix chunk key encodings. It is also flexible enough to cover the core default and v2 chunk key encodings.
It also brings the possibility of accessing legacy arrays stored as stacks of images (e.g. as used by CATMAID) directly through zarr.
Implementations
rust: template_cke
- appropriate for standalone usage
- optional (default) feature for usage with zarrs
python: zarr-python-template
- entry point for usage with zarr-python
