Skip to content

Tag sections

Tags are how RAD is self-describing. Instead of hard-coding which fields a record contains, the prelude declares them in three tag sections, and a reader configures its parser from those declarations.

SectionA value appears…Typical contents
File tagsonce, right after the preludebarcode length, UMI length, global metadata
Read tagsonce per read (record)cell barcode, UMI
Alignment tagsonce per alignment within a recordreference ID, orientation, position

The distinction is about where the value lives, not what it means. A read-level field is written once per read and shared by all of that read’s alignments; an alignment-level field is written once per alignment.

Each of the three sections is written as:

[ num_tags : u16 ][ descriptor_0 ][ descriptor_1 ] … [ descriptor_{num_tags-1} ]

A reader parses all three sections — file, then read, then alignment — in order.

Each descriptor names a field and gives its type:

[ name : string ] # u16 length + bytes
[ type_id : u8 ] # a RAD type identifier
( if type_id == 7 (array): [ length_type : u8 ][ element_type : u8 ] )
( if versioned (v2): [ role : … ] ) # see Tag roles

In a versioned file, every descriptor — in all three sections — additionally carries a semantic role suffix, which is what lets a reader locate the barcode, UMI, reference, and orientation fields without relying on tag-name conventions. Legacy files carry no role bytes.

Within a section, all fixed-width descriptors must come before any variable-width one (string or array). This lets a reader compute the byte stride of the fixed portion of a record up front and validate that a chunk’s records exactly fill its declared byte length — a cheap integrity check the reference implementation performs on the first chunk.

A typical single-cell RNA RAD declares:

  • File tags: cblen : u16, ulen : u16 — the barcode and UMI lengths.
  • Read tags: b (barcode, e.g. u32/u64), u (UMI, e.g. u32/u64).
  • Alignment tags: a reference/orientation field (often an orientation + ref ID word) per alignment.

A reader that understands these names (legacy) or reads their v2 roles knows how to extract the barcode, the UMI, and each alignment’s target — without the format prescribing a single fixed record struct.