Repository navigation
fix: write subsystems as strings in the MATLAB export - #165
Merged
Merged
Conversation
read_yaml_model keeps a reaction's subsystem as a list, as the YAML format writes it, but cobra's save_matlab_model only handles a string and fails on a list. export_for_git now joins them with subsystem_to_str for the .mat file, as export_to_excel already does, on a copy of the model.
edkerk
added a commit
that referenced
this pull request
Oct 7, 2026
The .mat export delegated to cobra's save_matlab_model, which writes a COBRA Toolbox structure: COBRA's field names (description/modelName, rxnECNumbers, geneNames), no slot for version, date, annotation, metFrom/rxnFrom, rxnNotes/rxnReferences/rxnConfidenceScores, inchis or the *Miriams structs, and rev as a platform-width integer. An integer rev makes RAVEN's mergeLinear fail on `S(...).' > 0 | rev`, which MATLAB rejects as a sparse integer operation. io.mat now writes and reads the RAVEN structure directly. The layout follows what RAVEN's own exporter produces, taken from the released yeast-GEM and Human-GEM files: writing yeast-GEM through it reproduces RAVEN's own yeast-GEM.mat field for field, with the same classes, shapes, sparsity and nested subSystems/MIRIAM structures. metComps is the one integer column, so a reader that turns the 1-based index into a position gets one; it is signed, so a metabolite with no compartment goes negative on that subtraction rather than wrapping round. The SBML export lost five fields to RAVEN's importModel. Only subSystems was actually absent, because cobra writes the groups package from model.groups and a model read from YAML carries its subsystems on the reaction; rxnNotes, rxnReferences and rxnConfidenceScores were present under cobra's key names rather than the labels importModel parses, and the model note was not written as its own notes entry. _for_sbml shapes a copy for the SBML write, leaving the caller's model alone. This supersedes #165, which joined subsystems into a string for cobra's writer; the RAVEN writer keeps them as a cell per reaction.
edkerk
added a commit
that referenced
this pull request
Oct 7, 2026
* fix: write RAVEN-format .mat and RAVEN-readable SBML The .mat export delegated to cobra's save_matlab_model, which writes a COBRA Toolbox structure: COBRA's field names (description/modelName, rxnECNumbers, geneNames), no slot for version, date, annotation, metFrom/rxnFrom, rxnNotes/rxnReferences/rxnConfidenceScores, inchis or the *Miriams structs, and rev as a platform-width integer. An integer rev makes RAVEN's mergeLinear fail on `S(...).' > 0 | rev`, which MATLAB rejects as a sparse integer operation. io.mat now writes and reads the RAVEN structure directly. The layout follows what RAVEN's own exporter produces, taken from the released yeast-GEM and Human-GEM files: writing yeast-GEM through it reproduces RAVEN's own yeast-GEM.mat field for field, with the same classes, shapes, sparsity and nested subSystems/MIRIAM structures. metComps is the one integer column, so a reader that turns the 1-based index into a position gets one; it is signed, so a metabolite with no compartment goes negative on that subtraction rather than wrapping round. The SBML export lost five fields to RAVEN's importModel. Only subSystems was actually absent, because cobra writes the groups package from model.groups and a model read from YAML carries its subsystems on the reaction; rxnNotes, rxnReferences and rxnConfidenceScores were present under cobra's key names rather than the labels importModel parses, and the model note was not written as its own notes entry. _for_sbml shapes a copy for the SBML write, leaving the caller's model alone. This supersedes #165, which joined subsystems into a string for cobra's writer; the RAVEN writer keeps them as a cell per reaction. * feat: read a COBRA Toolbox .mat as well as a RAVEN one read_matlab_model assumed a RAVEN structure, so a COBRA one came back half-read and silently: the skeleton (stoichiometry, bounds, GPRs, subsystems, compartments, charges, formulas) was right, but everything COBRA keeps under its own names was dropped -- the identifier (description/modelName), EC codes (rxnECNumbers), gene names (geneNames) and every cross-reference field. A COBRA structure is now recognised and handed to cobra's own reader, which already knows all of those mappings, rather than repeating the table here; the result has its annotations normalised to lists so a model read from either layout looks the same as one from read_yaml_model. A struct that is neither raises instead of returning something plausible but wrong. Human-GEM 2.0.1 and 2.1.0 shipped a COBRA-format .mat, so this is the way back from those releases: reading one and writing it out again produces the RAVEN file they should have had. * fix: type annotations in io.mat Three loops over a float column reused the variable the string loops above bound, the subsystem accumulator had no annotation, and the metadata dict holds the default bounds as floats beside its string fields.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
export_for_gitnow writes subsystems as strings in the.matfile.read_yaml_modelkeeps a reaction's subsystem as a list, as the YAML format writes it (even for one subsystem). cobra'ssave_matlab_modelonly handles a string, and fails withTypeError: unhashable type: 'numpy.ndarray'when given a list. So any model read from a RAVEN 3-format YAML could not be exported to.mat. This was found when building Human-GEM 2.1.0 from its RAVEN 3-format YAML (SysBioChalmers/Human-GEM#1124)._string_subsystemsgives the MATLAB export a copy of the model with each subsystem joined bysubsystem_to_str(a single subsystem stays its name; several are joined with;), asexport_to_excelalready does. The model passed in is not changed, and a model without list subsystems is exported as before..mat, reads back asGlycolysisandTransport;Exchange, and keeps its lists. The test fails without the fix.The full suite (1055 tests) and
ruff check src testspass on Vera.