YAML file format#
The YAML format is produced and consumed by three tools:
cobrapy (
cobra.io.{load,save}_yaml_model)raven-toolbox (
raven_toolbox.io.yaml.{read,write}_yaml_model, see API)RAVEN MATLAB (
readYAMLmodel.mandwriteYAMLmodel.min the RAVEN repo)
The same file can be round-tripped through any of the three. cobrapy defines the core shape. raven-toolbox and RAVEN MATLAB add namespaced extensions (RAVEN curation fields, MIRIAM cross-references already covered by cobrapy's annotation, and the GECKO ec-* sections) that leave the cobra-known shape intact.
Overview#
!!omap
- metaData: !!omap
- id: yeastGEM_develop
- name: The Consensus Genome-Scale Metabolic Model of Yeast
- version: 9.0.0
- date: 2026-05-27
- taxonomy: taxonomy/559292
- metabolites:
- !!omap
- id: s_0001
- name: ATP
- compartment: c
- charge: -4
- formula: C10H16N5O13P3
- annotation: !!omap
- kegg.compound: C00002
- smiles: "[O-]P(=O)([O-])OP(=O)([O-])O..."
- inchis: InChI=1S/C10H16N5O13P3/...
- deltaG: -2768.1
- reactions:
- !!omap
- id: r_0001
- name: hexokinase
- metabolites: !!omap
- s_0001: -1.0
- s_0568: -1.0
- s_0394: 1.0
- s_0423: 1.0
- lower_bound: 0.0
- upper_bound: 1000.0
- gene_reaction_rule: YGL253W or YCL040W or YFR053C
- subsystem: Glycolysis / Gluconeogenesis
- notes: "MetaNetX ID curated (PR #220)"
- annotation: !!omap
- kegg.reaction: R00299
- sbo: SBO:0000176
- eccodes: 2.7.1.1
- deltaG: -17.39
- confidence_score: 2.0
- genes:
- !!omap
- id: YGL253W
- name: HXK2
- annotation: !!omap
- uniprot: P04807
- compartments: !!omap
- c: cytoplasm
- e: extracellular
Three structural rules apply throughout the field-by-field description:
The whole document is one ordered mapping (
!!omap) at the root. Every nested map that preserves key order is also!!omap(metaData, each metabolite, reaction and gene entry,annotation,metabolites,compartments, and the ec sections).Each metabolite, reaction, and gene is one
- !!omapelement of a list. Inside that mapping, every field is written as- key: value. This is cobrapy's native shape, and RAVEN MATLAB's reader depends on it.Strings are unquoted by default. Quotes appear only when YAML would otherwise misparse the value (an empty string; a leading indicator character;
-,?or:followed by whitespace; embedded:or#; values that read astrue,false,y,n,yes,no,on,off,null, a number or a date). The section on numbers, strings and quoting lists the cases.
Top-level layout#
!!omap
- metaData: !!omap # optional; RAVEN extension
- metabolites: # required
- reactions: # required
- genes: # required (may be `genes: []`)
- compartments: !!omap # required
- gecko_light: <bool> # optional; GECKO extension
- ec-rxns: # optional; GECKO extension
- ec-enzymes: # optional; GECKO extension
Key |
Required |
Source |
Notes |
|---|---|---|---|
|
optional |
RAVEN |
Provenance block. Holds |
|
yes |
cobra core |
Ordered list of |
|
yes |
cobra core |
Ordered list of |
|
yes |
cobra core |
Ordered list; may be |
|
yes |
cobra core |
|
|
optional |
GECKO |
Scalar boolean. Cobrapy and raven-toolbox emit this at the top level; the spelling |
|
optional |
GECKO |
Per-reaction coupling table of kcat, source and enzymes. |
|
optional |
GECKO |
Per-enzyme table of MW, sequence and concentration. |
Cobrapy writes id, name and version at the root level and not inside metaData. The RAVEN readers accept both placements, and the RAVEN writers write the metaData form.
Metabolite entry#
Field order (cobra-core first, then RAVEN extensions):
- !!omap
- id: s_0001 # required
- name: ATP # cobra
- compartment: c # cobra
- charge: -4 # cobra (number)
- formula: C10H16N5O13P3 # cobra
- notes: "free-text" # cobra
- annotation: !!omap # cobra (MIRIAM + smiles)
- kegg.compound: C00002
- chebi:
- CHEBI:15422
- CHEBI:30616
- sbo: SBO:0000247
- smiles: "OC1=NC..." # quoted when it contains [ ] : etc.
- inchis: "InChI=1S/..." # RAVEN extension
- deltaG: -2768.1 # RAVEN extension
- metFrom: KEGG # RAVEN extension
Cobrapy emits exactly the first seven keys (the cobra-core block). raven-toolbox and RAVEN MATLAB additionally emit inchis, deltaG, and metFrom when those fields are populated. On read, cobrapy puts the RAVEN extensions on the metabolite as attribute fall-through, raven-toolbox captures them into metabolite.notes (keyed by their YAML name), and RAVEN MATLAB stores them on model.inchis, model.metDeltaG and model.metFrom.
Annotation entries with multiple values are emitted as a YAML list (chebi: then several - items). Single-value entries are emitted inline (kegg.compound: C00002). SMILES strings are stored inside the annotation block under the smiles key. A smiles field at the top level of a metabolite entry is also accepted on read.
Reaction entry#
- !!omap
- id: r_0001 # required
- name: hexokinase # cobra
- metabolites: !!omap # cobra (sorted by met id)
- s_0001: -1.0
- s_0394: 1.0
- lower_bound: 0.0 # cobra (number)
- upper_bound: 1000.0 # cobra (number)
- gene_reaction_rule: YGL253W or YCL040W # cobra
- objective_coefficient: 1 # cobra; omitted when 0
- subsystem: Glycolysis / Gluconeogenesis # cobra
- notes: "MetaNetX ID curated (PR #220)" # cobra
- annotation: !!omap # cobra
- kegg.reaction: R00299
- sbo: SBO:0000176
- eccodes: # RAVEN extension
- 2.7.1.1
- 2.7.1.2
- references: "PMID:12345" # RAVEN extension
- rxnFrom: KEGG # RAVEN extension
- deltaG: -17.39 # RAVEN extension
- confidence_score: 2.0 # RAVEN extension
Some fields are conditional:
objective_coefficientis only written when non-zero (cobrapy convention).The
metabolitesblock uses!!omap [](flow-style empty omap) when the reaction has no metabolites, which keeps the file a valid YAML 1.2 document.eccodesis written inline (eccodes: 2.7.1.1) when there is one code, and as a list when there are several. The same applies toreferences.
Cobrapy and the raven-toolbox and RAVEN MATLAB writers use the key notes. Some yeast-GEM files use rxnNotes, a legacy alias that both readers accept.
A notes entry can be a string or a mapping. raven-toolbox writes one for notes that have no RAVEN field, for example the base id that merge_compartments stores on each merged metabolite, with the free-text note under the key note. raven-toolbox reads such a mapping back into notes. RAVEN shows it in metNotes, and a round trip through RAVEN YAML or a .mat file does not retain it.
raven-toolbox reads gene_reaction_rule with the grammar of RAVEN's parseGrRule. RAVEN's reader splits rules with getGenesFromGrRules, which needs a space on each side of a lowercase and, or, & or | unless the operator touches a bracket, so G1&G2 is one gene id and G1 & G2 is two genes joined by and. Brackets next to an operator make no difference, because getGenesFromGrRules inserts a space in )and, and(, )or, or(, )&, &(, )| and |(. raven-toolbox also accepts the spellings AND, OR, && and ||, which RAVEN's reader leaves inside a gene id.
Bounds are emitted as floats with an explicit decimal point (1000.0, -1000.0), matching Python's float repr and cobrapy's output.
Gene entry#
- !!omap
- id: YGL253W # required
- name: HXK2 # cobra; omitted when empty
- annotation: !!omap # cobra
- uniprot: P04807
- ncbigene: 856421
- protein: P04807 # RAVEN extension
Empty names (name: '') are not emitted (matches RAVEN MATLAB's behaviour).
Compartments#
- compartments: !!omap
- c: cytoplasm
- e: extracellular
- m: mitochondrion
An !!omap of <short code>: <human-readable name> pairs. Compartments carry no MIRIAM annotations of their own in the format.
metaData (RAVEN extension)#
- metaData: !!omap
- id: yeastGEM_develop
- name: The Consensus Genome-Scale Metabolic Model of Yeast
- version: 9.0.0
- date: 2026-05-27
- defaultLB: -1000.0
- defaultUB: 1000.0
- givenName: Eduard
- familyName: Kerkhoven
- email: eduardk@chalmers.se
- organization: Chalmers University of Technology
- taxonomy: taxonomy/559292
- note: "Saccharomyces cerevisiae - strain S288C"
- sourceUrl: https://github.com/SysBioChalmers/yeast-GEM
The block holds provenance. Cobrapy ignores the block. raven-toolbox keeps the verbatim dictionary on model.notes['metaData'] and lifts id, name and version to model.id, model.name and model.notes['version'], where cobra-shape accessors find them. RAVEN MATLAB populates model.id, model.name, model.version and model.annotation.* from the same fields.
date is preserved across round-trips when present on the model. Otherwise the writer fills in YYYY-MM-DD of the current date.
GECKO sections#
Enzyme-constrained models carry the EC layer in three additional top-level keys:
- gecko_light: false # true for the "light" formulation
- ec-rxns:
- !!omap
- id: r_0001
- kcat: 25.3
- source: brenda
- notes: ""
- eccodes: 2.7.1.1
- enzymes: !!omap
- P04807: 1.0
- ec-enzymes:
- !!omap
- genes: YGL253W
- enzymes: P04807
- mw: 53942
- sequence: "MVHLGPK..."
- concs: .nan
The sections map onto model.ec in RAVEN MATLAB and raven_toolbox.io.ec_data.EcData (attached as model.ec) in raven-toolbox. Cobrapy ignores the sections.
An - enzymes: !!omap line with nothing under the tag is read as a reaction with no enzymes.
The spelling geckoLight inside metaData is also accepted on read.
Annotations#
The annotation block uses MIRIAM-style namespace keys. Cobrapy treats the block as a free-form dictionary, raven-toolbox preserves it verbatim through cobra.Metabolite.annotation, Reaction.annotation and Gene.annotation, and RAVEN MATLAB maps it to model.metMiriams, rxnMiriams and geneMiriams.
A single value is written inline:
kegg.compound: C00002.Multiple values are written as a YAML list:
- chebi: - CHEBI:15422 - CHEBI:30616
The
smileskey inside a metabolite'sannotationcarries the SMILES string (cobrapy convention). Both readers also acceptsmilesas a metabolite top-level field, and the writers use the annotation block.The
sbokey carries the Systems Biology Ontology term assigned byassignSBOterms/add_sbo_terms.
Numbers, strings and quoting#
Whole-number floats are written with an explicit .0 (1000.0, -1000.0, 0.0). Other floats use up to 15 significant digits (-17.39, -2768.1). NaN is encoded as .nan, and +Inf and -Inf as .inf and -.inf (YAML 1.2 conventions).
The default string style is bare (no quotes). raven-toolbox and RAVEN MATLAB apply the same rules and use double-quoted style when the value:
is empty;
starts with one of
#,,,[,],{,},&,*,!,|,>,',",%,@or`;is
-,?or:alone, or starts with one of them followed by whitespace;contains
:followed by whitespace or at the end of the value, or#after whitespace;has leading or trailing whitespace or contains a line break;
would be read as a non-string:
trueorfalsein lower, capitalised or upper case,y,n,yes,no,onoroffin any case (the YAML 1.1 booleans),null,Null,NULL,~, an integer or float (including hexadecimal, octal, binary,.infand.nanforms) or a date in the formYYYY-MM-DD.
The characters [, ], { and } inside a value do not trigger quoting.
In a double-quoted string, only \ and " are escaped. Other characters (including Unicode, and newlines if the underlying model permits them) are passed through.
The raven-toolbox reader repairs three quoted shapes that are not valid YAML: ""text"", a double-quoted scalar with an unescaped inner quote ("a "b" c"), and a single-quoted scalar with an inner apostrophe ('it's'). The values are "text", a "b" c and it's, as readYAMLmodel reads them. The repair runs when the strict parse fails and does not handle a comment after the closing quote.
Tool interoperability#
File written by (rows) and reader (columns) |
cobrapy |
raven-toolbox |
RAVEN MATLAB |
|---|---|---|---|
cobrapy ( |
full |
full, with extras in |
full, including root-level |
raven-toolbox ( |
core (no |
full |
full |
RAVEN MATLAB ( |
core (no |
full |
full |
"Full" means that every field is read back into its canonical position on the model object. "Core" means that cobrapy-known fields are read and RAVEN extensions are ignored or kept on the object as attribute fall-through (for example reaction.eccodes, not re-emitted on save). A round-trip through cobrapy is therefore lossy for RAVEN extensions: only the core fields survive cobrapy.load → cobrapy.save. Round-trips through raven-toolbox or RAVEN MATLAB are lossless.
Neither writer reproduces cobrapy's own ruamel-default layout byte-for-byte (indentation, quoting style, line folding). RAVEN and raven-toolbox share a layout with each other. The shared layout follows the structure of a cobrapy file and differs from it in details such as indentation and quoting. raven-gecko-parity's reconciliation record gives the reason and the one scenario (yaml_roundtrip_smallyeast) that continuously checks that the two writers agree.
Round-trip content counts#
Loading yeast-GEM.yml (2748 metabolites, 4102 reactions, 1143 genes) and re-writing it through any of the three tools preserves every documented piece of content:
Count |
After round-trip |
|---|---|
metabolites |
2748 / 2748 |
reactions |
4102 / 4102 |
genes |
1143 / 1143 |
reactions with eccodes |
2411 |
reactions with deltaG |
3984 |
metabolites with deltaG |
2696 |
metabolites with SMILES |
1788 |
reactions with notes (rxnNotes) |
1443 |
Cobrapy round-trips give 2748 / 4102 / 1143 for the core and drop the RAVEN extensions in the rightmost column, which is the documented loss.