Skip to main content

parse_feature_row

Function parse_feature_row 

Source
pub fn parse_feature_row(name: &str) -> Option<FeatureRow<'_>>
Expand description

Split a feature row into its fields. The channel is the innermost (last) field, so a 3-field row is gene-level ({gene}/{modality}/{channel}) and a 4-field row carries a subunit before the channel ({gene}/{modality}/{subunit}/{channel}).

§A unit may contain /

Counting fields alone is not enough, because real gene symbols contain slashes — standard human references ship at least one. Such a gene’s count row has four fields and used to parse as gene = {id}_GENE1, modality = GENE1B, subunit = count: not an error, just a different gene, so the two channel rows of that gene stopped pairing and nothing said so.

So the modality is located by NAME, scanned from the right against [MODALITIES], and whatever precedes it is the unit however many slashes it contains. The subunit and channel still may not contain / — they are a chr:pos, a component index, and a fixed token.

The two candidate positions are tried nearest-first, so a row whose unit ENDS in a modality token reads as the gene-level form: A/count/count/spliced is the gene A/count, not the gene A with a subunit called count. That ambiguity is unreachable in practice — a subunit is a chr:pos or a component index, never a modality name.

When NEITHER candidate position holds a known modality the old positional rule applies unchanged, so the producers that still emit their rows inline with a modality token outside the constant list (see the module docs) keep parsing exactly as they did. The vocabulary can only make a row parse BETTER, never make a row that parsed stop parsing.

Returns None for anything with fewer than three fields, or more than four when no known modality locates the split.