Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/memote-history.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v7
# MEMOTE wants to fetch all branches
with:
fetch-depth: 0


- name: Set up Python 3
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: "3.9"

- name: Install memote
run: pip install -r code/requirements/ci-requirements.txt

- name: Checkout repo for gh-pages branch
uses: actions/checkout@v3
uses: actions/checkout@v7
with:
repository: ${{ github.repository }}
ref: gh-pages
Expand All @@ -49,7 +49,7 @@ jobs:
git pull

- name: Auto-commit results
uses: stefanzweifel/git-auto-commit-action@v4
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_user_name: memote-bot
commit_message: "chore: update memote history report"
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/memote-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout main branch
uses: actions/checkout@v3
uses: actions/checkout@v7
with:
ref: main

- name: Checkout gh-pages branch
uses: actions/checkout@v3
uses: actions/checkout@v7
with:
ref: gh-pages
path: gh-pages-repo

- name: Set up Python 3
uses: actions/setup-python@v4
uses: actions/setup-python@v6
with:
python-version: "3.9"

Expand All @@ -40,7 +40,7 @@ jobs:
git pull

- name: Auto-commit results
uses: stefanzweifel/git-auto-commit-action@v4
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_user_name: memote-bot
commit_message: "chore: update memote release report"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/memote-run.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v7

- name: Create .env
run: |
Expand Down
106 changes: 106 additions & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Python

on:
push:
branches: [main, develop]
paths:
- 'code/python/**'
- 'code/io.py'
- 'data/yeastgem/**'
- 'data/conditions/**'
- 'data/essentialGenes/**'
- 'data/physiology/**'
- 'model/**'
- '.github/workflows/python.yml'
pull_request:
branches: [main, develop]
paths:
- 'code/python/**'
- 'code/io.py'
- 'data/yeastgem/**'
- 'data/conditions/**'
- 'data/essentialGenes/**'
- 'data/physiology/**'
- 'model/**'
- '.github/workflows/python.yml'

jobs:
# Unit tests + lint across the supported Python matrix. Fast (~5 min
# wall clock per Python version after caches warm).
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ['3.10', '3.11', '3.12']

steps:
- name: Checkout
uses: actions/checkout@v7

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: pip
cache-dependency-path: code/python/pyproject.toml

- name: Install yeastgem (editable, with dev deps)
run: pip install -e "code/python/[dev]"

- name: Lint with ruff
run: ruff check code/python

- name: Run pytest
working-directory: code/python
run: pytest -v

# Level-1 parity — Python SBML read+write of the committed
# model/yeast-GEM.xml must round-trip to a semantically-equal model.
# Catches SBML library regressions, annotation losses, and
# accidental id rewrites.
parity-level-1-round-trip:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: pip
cache-dependency-path: code/python/pyproject.toml

- name: Install yeastgem
run: pip install -e code/python/

- name: SBML round-trip preserves model
run: python code/python/tests/ci/check_round_trip.py

# Level-2 parity — Python validation metrics must match the
# committed MATLAB-produced reference within tolerance. Tolerances
# account for Gurobi-vs-HiGHS solver drift around the essential-gene
# 1e-6 growth-ratio threshold. Regenerate the reference via
# code/python/tests/reference/runPhase5Metrics.m when the metrics
# shift legitimately.
parity-level-2-metrics:
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout
uses: actions/checkout@v7

- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: pip
cache-dependency-path: code/python/pyproject.toml

- name: Install yeastgem
run: pip install -e code/python/

- name: Validation metrics match the committed reference
run: python code/python/tests/ci/check_metrics.py
2 changes: 1 addition & 1 deletion .github/workflows/yaml-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v7

- name: YAML Lint
uses: ibiqlik/action-yamllint@v1
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ helpsearch*/
*.ipynb_checkpoints/
*.pyc
*.env
__pycache__/
.pytest_cache/
.ruff_cache/
*.egg-info/
build/
dist/
.venv/

# Non-complying tables and files #
##################################
Expand Down
49 changes: 33 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,26 @@ Please see the installation instructions for each software package.
* [RAVEN Toolbox](https://github.com/SysBioChalmers/RAVEN) version 2.8.3 or later

* Python-based
Contribution via python (cobrapy) is not yet functional. In essence, if you can retain the same format of the model files, you can still contribute to the development of yeast-GEM. However, you cannot use the MATLAB functions.

If you want to use any of the [provided](https://github.com/SysBioChalmers/yeast-GEM/tree/main/code) Python functions, you may create an environment with all requirements:
Contribution via Python is supported through the `yeastgem` package
under [code/python/](code/python/) and its
[PORTING_PLAN.md](code/python/PORTING_PLAN.md). The package builds
on [cobrapy](https://github.com/opencobra/cobrapy) and
[raven-python](https://github.com/SysBioChalmers/raven-python) (the
Python port of RAVEN) — the latter provides the generic GEM
utilities (`diff_models`, `add_sbo_terms`, condition / biomass /
curation helpers) that `yeastgem` configures with the yeast-specific
data files under [data/](data/).

Install from a checkout:
```bash
pip install -r code/requirements/requirements.txt # install all dependencies
touch .env # create a .env file for locating the root
pip install -e code/python/[dev]
```

The release pipeline equivalent to the MATLAB `commitYeastModel`
is `yeastgem.commit_yeast_model`. The historical
[code/io.py](code/io.py) is kept as a deprecated forwarding shim
that re-exports from the new package.

If you want to locally run `memote run` or `memote report history`, you should also install [git lfs](https://git-lfs.github.com/), as `results.db` (the database that stores all memote results) is tracked with git lfs.

## Model usage
Expand All @@ -87,21 +99,26 @@ Make sure to load/save the model with the corresponding wrapper functions:
* In Matlab:
```matlab
cd ./code
model = loadYeastModel(); % loading
saveYeastModel(model); % saving
model = loadYeastModel(); % loading
commitYeastModel(model); % saving — release pipeline (was saveYeastModel)
```
* If RAVEN is not installed, you can also use COBRA-native functions (`readCbModel`, `writeCbModel`), but these model-files cannot be committed back to the GitHub repository.
* In Python:
Before opening Python, the following command should (once) be run in the yeast-GEM root folder:
```bash
touch .env # create a .env file for locating the root
```
Afterwards, the model can be loaded in Python with:
* `saveYeastModel` is kept as a deprecated shim that forwards to `commitYeastModel`; it emits a deprecation warning.
* In Python (after `pip install -e code/python/`):
```python
import code.io as io
model = io.read_yeast_model() # loading
io.write_yeast_model(model) # saving
from yeastgem import read_yeast_model, commit_yeast_model
model = read_yeast_model() # loading
commit_yeast_model(model) # saving — release pipeline (validates,
# applies canonical state, writes SBML +
# ΔG CSVs, updates README)
```
The Python release pipeline currently writes the `.xml` artifact and
the ΔG side-car CSVs; the `.yml` / `.txt` companion exports still
require running the MATLAB `commitYeastModel`. Anaerobic growth and
the model_tests benchmarks are wired in
[`yeastgem.model_tests`](code/python/yeastgem/model_tests/); batch
curation from TSV inputs is available via
[`yeastgem.curation`](code/python/yeastgem/curation.py).

### Online visualization

Expand Down
25 changes: 25 additions & 0 deletions code/applyIDs.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
function ids = applyIDs()
% applyIDs Load the canonical yeast-GEM identifiers from data/yeastgem/ids.yml.
%
% ids = applyIDs() returns a struct with fields:
% biomass_rxn string
% protein_rxn string
% cofactor_rxn string
% proton_met string
% pseudoreaction_names struct (component -> name)
% gam_cofactors cell array of strings
%
% This is the data-driven replacement for the hardcoded IDs that
% used to live in functions like changeGAM.m, rescalePseudoReaction.m,
% sumBioMass.m. Those functions are kept as legacy shims; new code
% should call applyIDs and read from the returned struct.
%
% Requires RAVEN's parseYAML (any RAVEN release ≥ the commit that
% added io/parseYAML.m, currently the feat/yeast-gem-shared branch).
%
% Usage: ids = applyIDs()

funcDir = fileparts(mfilename('fullpath'));
yamlPath = fullfile(funcDir, '..', 'data', 'yeastgem', 'ids.yml');
ids = parseYAML(yamlPath);
end
43 changes: 43 additions & 0 deletions code/applyYeastCondition.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
function model = applyYeastCondition(model, name)
% applyYeastCondition Apply a named yeast-GEM condition preset to the model.
%
% Yeast-specific wrapper around RAVEN's generic applyCondition. This
% function:
% 1. Resolves `name` to a YAML file under `data/conditions/`.
% 2. Applies the yeast-specific `amino_acid_ratio` step
% (via changeAminoAcidRatio) when present in the YAML.
% 3. Hands the parsed condition to RAVEN's `applyCondition` for
% the generic prelude / cofactor / biomass-delta / bounds /
% uptake-count steps.
%
% Available presets (data/conditions/<name>.yml):
% 'minimal_Y6' minimal media (replaces minimal_Y6.m)
% 'anaerobic' anaerobic conditions (replaces anaerobicModel.m)
% 'glycine_nitrogen' glycine as sole N source
% 'nitrogen_limitation' N-limited
%
% Requires RAVEN with the applyCondition / parseYAML helpers (commit
% on the feat/yeast-gem-shared branch or any later release that
% incorporates them).
%
% Usage: model = applyYeastCondition(model, 'anaerobic')

funcDir = fileparts(mfilename('fullpath'));
yamlPath = fullfile(funcDir, '..', 'data', 'conditions', [name '.yml']);
if ~isfile(yamlPath)
error('applyYeastCondition:unknownCondition', ...
'No such condition: %s (looked for %s)', name, yamlPath);
end
cond = parseYAML(yamlPath);

% Yeast-specific pre-step: amino_acid_ratio rewrites the protein
% pseudoreaction's stoichiometry from data/physiology/. The generic
% applyCondition silently ignores this field.
if isfield(cond, 'amino_acid_ratio')
aerobic = strcmp(cond.amino_acid_ratio, 'aerobic');
model = changeAminoAcidRatio(model, aerobic);
end

% Generic mechanism (provided by RAVEN).
model = applyCondition(model, cond);
end
Loading