Upload 18 files
Browse files- Cowmunity-litreturebased.py +1271 -0
- Cowmunity.py +1307 -0
- README.md +154 -0
- cow.txt +30 -0
- docking_data/cleaned_docking_results.csv +5 -0
- docking_data/key_protein_targets_for_docking.csv +5 -0
- docking_data/protein_targets_for_docking.xlsx +0 -0
- docking_data/protein_targets_for_docking_FINAL.csv +29 -0
- docking_integration/__init__.py +36 -0
- docking_integration/apply_docking_constraints.py +141 -0
- docking_integration/ds +1 -0
- docking_integration/enzyme_reaction_mapper.py +159 -0
- docking_integration/parse_docking_results.py +300 -0
- main.py +64 -0
- model files/M. gottschalkii.xml +0 -0
- model files/P. ruminicola.xml +0 -0
- model files/R. flavefaciens.xml +0 -0
- model files/new +1 -0
Cowmunity-litreturebased.py
ADDED
|
@@ -0,0 +1,1271 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import libsbml
|
| 3 |
+
from gamspy import Container, Set, Parameter, Variable, Equation, Model, Sum, Sense, Options, SpecialValues, SolveStatus
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
def Sets():
|
| 7 |
+
print("Creating sets...")
|
| 8 |
+
global cowmunity
|
| 9 |
+
|
| 10 |
+
cowmunity = Container()
|
| 11 |
+
|
| 12 |
+
global j_mgk, j_prm, j_rfl, i_mgk, i_prm, i_rfl
|
| 13 |
+
|
| 14 |
+
j_mgk = Set(container=cowmunity, name="j_mgk", description="M. Gottschalkii reactions")
|
| 15 |
+
j_prm = Set(container=cowmunity, name="j_prm", description="P. ruminicola reactions")
|
| 16 |
+
j_rfl = Set(container=cowmunity, name="j_rfl", description="R. flavefaciens reactions")
|
| 17 |
+
|
| 18 |
+
i_mgk = Set(container=cowmunity, name="i_mgk", description="M. Gottschalkii metabolites")
|
| 19 |
+
i_prm = Set(container=cowmunity, name="i_prm", description="P. ruminicola metabolites")
|
| 20 |
+
i_rfl = Set(container=cowmunity, name="i_rfl", description="R. flavefaciens metabolites")
|
| 21 |
+
|
| 22 |
+
def extract_metabolites(xml_file_path, GAMSpy_set):
|
| 23 |
+
# Parse the XML file
|
| 24 |
+
reader = libsbml.SBMLReader()
|
| 25 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 26 |
+
model = document.getModel()
|
| 27 |
+
if model is None:
|
| 28 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 29 |
+
|
| 30 |
+
# Extract names and store them in a list
|
| 31 |
+
met_name = {}
|
| 32 |
+
for i in range(model.getNumSpecies()):
|
| 33 |
+
species = model.getSpecies(i)
|
| 34 |
+
new_entry = {species.id : species.getName()[0:63]}
|
| 35 |
+
met_name.update(new_entry)
|
| 36 |
+
df = pd.DataFrame.from_dict(met_name, orient='index', columns=['name'])
|
| 37 |
+
|
| 38 |
+
# add the names to the GAMSpy Set
|
| 39 |
+
GAMSpy_set.setRecords(df.reset_index())
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def extract_reactions(xml_file_path, GAMSpy_set):
|
| 43 |
+
# Parse the XML file
|
| 44 |
+
reader = libsbml.SBMLReader()
|
| 45 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 46 |
+
model = document.getModel()
|
| 47 |
+
if model is None:
|
| 48 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 49 |
+
|
| 50 |
+
# Extract names and store them in a list
|
| 51 |
+
rxn_name = {}
|
| 52 |
+
for i in range(model.getNumReactions()):
|
| 53 |
+
reaction = model.getReaction(i)
|
| 54 |
+
new_entry = {reaction.id : reaction.getName()[0:63]}
|
| 55 |
+
rxn_name.update(new_entry)
|
| 56 |
+
df = pd.DataFrame.from_dict(rxn_name, orient='index', columns=['name'])
|
| 57 |
+
|
| 58 |
+
# add the names to the GAMSpy Set
|
| 59 |
+
GAMSpy_set.setRecords(df.reset_index())
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
extract_reactions('M. gottschalkii.xml', j_mgk)
|
| 63 |
+
extract_reactions('P. ruminicola.xml', j_prm)
|
| 64 |
+
extract_reactions('R. flavefaciens.xml', j_rfl)
|
| 65 |
+
|
| 66 |
+
extract_metabolites('M. gottschalkii.xml', i_mgk)
|
| 67 |
+
extract_metabolites('P. ruminicola.xml', i_prm)
|
| 68 |
+
extract_metabolites('R. flavefaciens.xml', i_rfl)
|
| 69 |
+
|
| 70 |
+
def Parameters():
|
| 71 |
+
print("Adding model parameters...")
|
| 72 |
+
global ub_mgk, ub_prm, ub_rfl, lb_mgk, lb_prm, lb_rfl
|
| 73 |
+
|
| 74 |
+
ub_mgk = Parameter(container=cowmunity, name="ub_mgk", domain=j_mgk, description="Upper bound for M. Gottschalkii reactions")
|
| 75 |
+
lb_mgk = Parameter(container=cowmunity, name="lb_mgk", domain=j_mgk, description="Lower bound for M. Gottschalkii reactions")
|
| 76 |
+
|
| 77 |
+
ub_prm = Parameter(container=cowmunity, name="ub_prm", domain=j_prm, description="Upper bound for P. ruminicola reactions")
|
| 78 |
+
lb_prm = Parameter(container=cowmunity, name="lb_prm", domain=j_prm, description="Lower bound for P. ruminicola reactions")
|
| 79 |
+
|
| 80 |
+
ub_rfl = Parameter(container=cowmunity, name="ub_rfl", domain=j_rfl, description="Upper bound for R. flavefaciens reactions")
|
| 81 |
+
lb_rfl = Parameter(container=cowmunity, name="lb_rfl", domain=j_rfl, description="Lower bound for R. flavefaciens reactions")
|
| 82 |
+
|
| 83 |
+
# define the reaction types for each reaction, whether they are reversible (1) or irreversible (0)
|
| 84 |
+
|
| 85 |
+
rxntype_mgk = Parameter(container=cowmunity, name="rxntype_mgk", domain=j_mgk, description="Reaction type for M. Gottschalkii reactions")
|
| 86 |
+
rxntype_prm = Parameter(container=cowmunity, name="rxntype_prm", domain=j_prm, description="Reaction type for P. ruminicola reactions")
|
| 87 |
+
rxntype_rfl = Parameter(container=cowmunity, name="rxntype_rfl", domain=j_rfl, description="Reaction type for R. flavefaciens reactions")
|
| 88 |
+
|
| 89 |
+
# define the stoichiometric matrix for each species, which describes the relationship between reactions and metabolites
|
| 90 |
+
# gives the coefficients for each reaction
|
| 91 |
+
|
| 92 |
+
global S_mgk, S_prm, S_rfl
|
| 93 |
+
|
| 94 |
+
S_mgk = Parameter(container=cowmunity, name="S_mgk", domain=[j_mgk, i_mgk], description="Stoichiometric matrix for M. Gottschalkii")
|
| 95 |
+
S_prm = Parameter(container=cowmunity, name="S_prm", domain=[j_prm, i_prm], description="Stoichiometric matrix for P. ruminicola")
|
| 96 |
+
S_rfl = Parameter(container=cowmunity, name="S_rfl", domain=[j_rfl, i_rfl], description="Stoichiometric matrix for R. flavefaciens")
|
| 97 |
+
|
| 98 |
+
# define whether each reaction is an exchange reaction
|
| 99 |
+
|
| 100 |
+
ex_mgk = Parameter(container=cowmunity, name="ex_mgk", domain=j_mgk, description="Exchange for M. Gottschalkii reactions")
|
| 101 |
+
ex_prm = Parameter(container=cowmunity, name="ex_prm", domain=j_prm, description="Exchange for P. ruminicola reactions")
|
| 102 |
+
ex_rfl = Parameter(container=cowmunity, name="ex_rfl", domain=j_rfl, description="Exchange for R. flavefaciens reactions")
|
| 103 |
+
|
| 104 |
+
def extract_rxn_type(xml_file_path, GAMSpy_parameter):
|
| 105 |
+
# Parse the XML file
|
| 106 |
+
reader = libsbml.SBMLReader()
|
| 107 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 108 |
+
model = document.getModel()
|
| 109 |
+
if model is None:
|
| 110 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 111 |
+
# Extract names and store them in a list
|
| 112 |
+
type_dict = {}
|
| 113 |
+
for i in range(model.getNumReactions()):
|
| 114 |
+
reaction = model.getReaction(i)
|
| 115 |
+
rxn_type = reaction.getReversible()
|
| 116 |
+
if rxn_type:
|
| 117 |
+
rxn_type = 1
|
| 118 |
+
else:
|
| 119 |
+
rxn_type = 0
|
| 120 |
+
new_entry = {reaction.id : rxn_type}
|
| 121 |
+
type_dict.update(new_entry)
|
| 122 |
+
|
| 123 |
+
df = pd.DataFrame.from_dict(type_dict, orient='index', columns=['name'])
|
| 124 |
+
|
| 125 |
+
# add the names to the GAMSpy Set
|
| 126 |
+
GAMSpy_parameter.setRecords(df.reset_index())
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def extract_matrix(xml_file_path, GAMSpy_parameter):
|
| 130 |
+
# Parse the XML file
|
| 131 |
+
reader = libsbml.SBMLReader()
|
| 132 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 133 |
+
model = document.getModel()
|
| 134 |
+
if model is None:
|
| 135 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 136 |
+
# Extract reactions, metabolites, and their stoichiometry
|
| 137 |
+
df = pd.DataFrame()
|
| 138 |
+
for i in range(model.getNumReactions()):
|
| 139 |
+
reaction = model.getReaction(i)
|
| 140 |
+
for i in range(reaction.getNumReactants()):
|
| 141 |
+
reactant = reaction.getReactant(i)
|
| 142 |
+
metabolite_id = reactant.species
|
| 143 |
+
stoich = reactant.stoichiometry
|
| 144 |
+
new_row_df = pd.DataFrame({'reaction': [reaction.id], 'metabolite': [metabolite_id], 'stoichiometry': [-stoich]})
|
| 145 |
+
df = pd.concat([df, new_row_df], ignore_index=True)
|
| 146 |
+
for i in range(reaction.getNumProducts()):
|
| 147 |
+
product = reaction.getProduct(i)
|
| 148 |
+
metabolite_id = product.species
|
| 149 |
+
stoich = product.stoichiometry
|
| 150 |
+
new_row_df = pd.DataFrame({'reaction': [reaction.id], 'metabolite': [metabolite_id], 'stoichiometry': [stoich]})
|
| 151 |
+
df = pd.concat([df, new_row_df], ignore_index=True)
|
| 152 |
+
|
| 153 |
+
df = df.set_index(['reaction', 'metabolite'])
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
# add the names to the GAMSpy Set
|
| 157 |
+
GAMSpy_parameter.setRecords(df.reset_index())
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
def extract_exchange_type(xml_file_path, GAMSpy_parameter):
|
| 161 |
+
# Parse the XML file
|
| 162 |
+
reader = libsbml.SBMLReader()
|
| 163 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 164 |
+
model = document.getModel()
|
| 165 |
+
if model is None:
|
| 166 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 167 |
+
# Extract names and store them in a list
|
| 168 |
+
type_dict = {}
|
| 169 |
+
ex_count = 0
|
| 170 |
+
for i in range(model.getNumReactions()):
|
| 171 |
+
reaction = model.getReaction(i)
|
| 172 |
+
if 'EX_' in reaction.id:
|
| 173 |
+
ex_type = 1
|
| 174 |
+
ex_count += 1
|
| 175 |
+
else:
|
| 176 |
+
ex_type = 0
|
| 177 |
+
new_entry = {reaction.id : ex_type}
|
| 178 |
+
type_dict.update(new_entry)
|
| 179 |
+
|
| 180 |
+
df = pd.DataFrame.from_dict(type_dict, orient='index', columns=['name'])
|
| 181 |
+
|
| 182 |
+
# add the names to the GAMSpy Set
|
| 183 |
+
GAMSpy_parameter.setRecords(df.reset_index())
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
extract_rxn_type('M. gottschalkii.xml', rxntype_mgk)
|
| 187 |
+
extract_rxn_type('P. ruminicola.xml', rxntype_prm)
|
| 188 |
+
extract_rxn_type('R. flavefaciens.xml', rxntype_rfl)
|
| 189 |
+
|
| 190 |
+
extract_matrix('M. gottschalkii.xml', S_mgk)
|
| 191 |
+
extract_matrix('P. ruminicola.xml', S_prm)
|
| 192 |
+
extract_matrix('R. flavefaciens.xml', S_rfl)
|
| 193 |
+
|
| 194 |
+
extract_exchange_type('M. gottschalkii.xml', ex_mgk)
|
| 195 |
+
extract_exchange_type('P. ruminicola.xml', ex_prm)
|
| 196 |
+
extract_exchange_type('R. flavefaciens.xml', ex_rfl)
|
| 197 |
+
|
| 198 |
+
# using a scalar parameter to define the maximum flux for each reaction, this is a constant that will be used in the model
|
| 199 |
+
|
| 200 |
+
Vmax = Parameter(container=cowmunity, name='Vmax', records=1000)
|
| 201 |
+
|
| 202 |
+
# set the reaction bounds for the irreversible reactions, reaction type 0
|
| 203 |
+
|
| 204 |
+
ub_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 0] = Vmax
|
| 205 |
+
lb_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 0] = SpecialValues.EPS # using SpecialValues.EPS to avoid zero lower bounds, which can cause issues in some solvers
|
| 206 |
+
|
| 207 |
+
ub_prm[j_prm].where[rxntype_prm[j_prm] == 0] = Vmax
|
| 208 |
+
lb_prm[j_prm].where[rxntype_prm[j_prm] == 0] = SpecialValues.EPS
|
| 209 |
+
|
| 210 |
+
ub_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 0] = Vmax
|
| 211 |
+
lb_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 0] = SpecialValues.EPS
|
| 212 |
+
|
| 213 |
+
# set the reaction bounds for the reversible reactions, reaction type 1
|
| 214 |
+
|
| 215 |
+
ub_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 1] = Vmax
|
| 216 |
+
lb_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 1] = -Vmax
|
| 217 |
+
|
| 218 |
+
ub_prm[j_prm].where[rxntype_prm[j_prm] == 1] = Vmax
|
| 219 |
+
lb_prm[j_prm].where[rxntype_prm[j_prm] == 1] = -Vmax
|
| 220 |
+
|
| 221 |
+
ub_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 1] = Vmax
|
| 222 |
+
lb_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 1] = -Vmax
|
| 223 |
+
|
| 224 |
+
def Variables(variable_choice, treatment='no', methane='variable'):
|
| 225 |
+
global v_mgk, v_prm, v_rfl, biomass_outer, ATP_outer, objective_variable
|
| 226 |
+
|
| 227 |
+
biomass_outer = Variable(container=cowmunity, name="biomass_outer", description="Outer problem Biomass objective function")
|
| 228 |
+
ATP_outer = Variable(container=cowmunity, name="ATP_outer", description="Outer problem ATP objective function")
|
| 229 |
+
|
| 230 |
+
if variable_choice == 'biomass_outer':
|
| 231 |
+
objective_variable = biomass_outer
|
| 232 |
+
if variable_choice == 'ATP_outer':
|
| 233 |
+
objective_variable = ATP_outer
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
v_mgk = Variable(container=cowmunity, name="v_mgk", domain=j_mgk, description="Fluxes for M. Gottschalkii reactions")
|
| 237 |
+
v_prm = Variable(container=cowmunity, name="v_prm", domain=j_prm, description="Fluxes for P. ruminicola reactions")
|
| 238 |
+
v_rfl = Variable(container=cowmunity, name="v_rfl", domain=j_rfl, description="Fluxes for R. flavefaciens reactions")
|
| 239 |
+
|
| 240 |
+
global lambda_mgk, lambda_prm, lambda_rfl
|
| 241 |
+
|
| 242 |
+
# Dual variables for the mass balance
|
| 243 |
+
lambda_mgk = Variable(container=cowmunity, name="lambda_mgk", domain=i_mgk, description="Dual variables for M. Gottschalkii metabolites")
|
| 244 |
+
lambda_prm = Variable(container=cowmunity, name="lambda_prm", domain=i_prm, description="Dual variables for P. ruminicola metabolites")
|
| 245 |
+
lambda_rfl = Variable(container=cowmunity, name="lambda_rfl", domain=i_rfl, description="Dual variables for R. flavefaciens metabolites")
|
| 246 |
+
|
| 247 |
+
# defining the flux bounds for each reaction as the upper and lower bounds defined above
|
| 248 |
+
v_mgk.lo[j_mgk] = lb_mgk[j_mgk]
|
| 249 |
+
v_mgk.up[j_mgk] = ub_mgk[j_mgk]
|
| 250 |
+
v_prm.lo[j_prm] = lb_prm[j_prm]
|
| 251 |
+
v_prm.up[j_prm] = ub_prm[j_prm]
|
| 252 |
+
v_rfl.lo[j_rfl] = lb_rfl[j_rfl]
|
| 253 |
+
v_rfl.up[j_rfl] = ub_rfl[j_rfl]
|
| 254 |
+
|
| 255 |
+
# ****** indicates the metabolite is transferred between species, so I will not set a flux for the species that does not take it up
|
| 256 |
+
# commented lines are those determined to have a greater capacity due to the potential for transfer between species
|
| 257 |
+
# the 4.55 indicates a conversion factor for dry whole weight to dry cell weight, as the model is based on dry cell weight
|
| 258 |
+
|
| 259 |
+
# v_prm.lo['EX_cpd11657_e0'] = -0.965423023 * 4.55 # uptake rate for Starch, fed to the model as two glucose units
|
| 260 |
+
v_prm.lo['EX_cpd00076_e0'] = -0.834726132 * 4.55 # uptake rate for Sucrose
|
| 261 |
+
v_rfl.lo['EX_cpd00076_e0'] = -0.834726132 * 4.55
|
| 262 |
+
v_prm.lo['EX_cpd00053_e0'] = -1.597816364 * 4.55 # uptake rate for L-Glutamine
|
| 263 |
+
v_rfl.lo['EX_cpd00053_e0'] = -1.597816364 * 4.55
|
| 264 |
+
# v_prm.lo['EX_cpd00027_e0'] = -0.794397609 * 4.55 # uptake rate for D-glucose *****
|
| 265 |
+
v_rfl.lo['EX_cpd00027_e0'] = (-0.794397609 + (-0.965423023 * 2)) * 4.55 # adjusted for the uptake of Starch
|
| 266 |
+
v_rfl.lo['EX_cpd00107_e0'] = -1.148366562 * 4.55 # uptake rate for L-Leucine
|
| 267 |
+
v_prm.lo['EX_cpd00107_e0'] = -1.148366562 * 4.55
|
| 268 |
+
# v_prm.lo['EX_cpd00224_e0'] = -0.666427627 * 4.55 # uptake rate for L-arabinose *****
|
| 269 |
+
v_rfl.lo['EX_cpd00224_e0'] = -0.666427627 * 4.55
|
| 270 |
+
# v_prm.lo['EX_cpd00035_e0'] = -0.938846598 * 4.55 # uptake rate for L-Alanine ****
|
| 271 |
+
# v_rfl.lo['EX_cpd00035_e0'] = -0.938846598 * 4.55
|
| 272 |
+
v_prm.lo['EX_cpd00132_e0'] = -0.400330802 * 4.55 # uptake rate for L-Asparagine
|
| 273 |
+
v_rfl.lo['EX_cpd00066_e0'] = -0.310015056 * 4.55 # uptake rate for L-Phenylalanine
|
| 274 |
+
v_rfl.lo['EX_cpd00156_e0'] = -0.385856944 * 4.55 # uptake rate for L-Valine
|
| 275 |
+
v_rfl.lo['EX_cpd00069_e0'] = -0.218417727 * 4.55 # uptake rate for L-Tyrosine
|
| 276 |
+
v_prm.lo['EX_cpd00060_e0'] = -0.233929798 * 4.55 # uptake rate for L-Methionine
|
| 277 |
+
v_prm.lo['EX_cpd00161_e0'] = -0.261179221 * 4.55 # uptake rate for L-Threonine
|
| 278 |
+
v_rfl.lo['EX_cpd00161_e0'] = -0.261179221 * 4.55
|
| 279 |
+
v_rfl.lo['EX_cpd00322_e0'] = -0.211165444 * 4.55 # uptake rate for L-Isoleucine
|
| 280 |
+
v_prm.lo['EX_cpd00051_e0'] = -0.133660701 * 4.55 # uptake rate for L-Arginine
|
| 281 |
+
v_rfl.lo['EX_cpd00051_e0'] = -0.133660701 * 4.55
|
| 282 |
+
# v_prm.lo['EX_cpd00033_e0'] = -0.268595078 * 4.55 # uptake rate for Glycine ******
|
| 283 |
+
# v_rfl.lo['EX_cpd00033_e0'] = -0.268595078 * 4.55
|
| 284 |
+
v_prm.lo['EX_cpd00348_e0'] = -0.075513967 * 4.55 # uptake rate for D-Galactose
|
| 285 |
+
v_rfl.lo['EX_cpd00348_e0'] = -0.075513967 * 4.55
|
| 286 |
+
v_rfl.lo['EX_cpd00119_e0'] = -0.124559013 * 4.55 # uptake rate for L-Histidine
|
| 287 |
+
v_prm.lo['EX_cpd00039_e0'] = -0.098373937 * 4.55 # uptake rate for L-Lysine
|
| 288 |
+
v_rfl.lo['EX_cpd00039_e0'] = -0.098373937 * 4.55
|
| 289 |
+
v_prm.lo['EX_cpd00084_e0'] = -0.114920408 * 4.55 # uptake rate for L-Cysteine
|
| 290 |
+
v_rfl.lo['EX_cpd00084_e0'] = -0.114920408 * 4.55
|
| 291 |
+
v_prm.lo['EX_cpd00053_e0'] = -0.080568485 * 4.55 # uptake rate for L-Glutamine
|
| 292 |
+
v_rfl.lo['EX_cpd00053_e0'] = -0.080568485 * 4.55
|
| 293 |
+
v_rfl.lo['EX_cpd00038_e0'] = -0.007734655 * 4.55 # uptake rate for GTP
|
| 294 |
+
v_rfl.lo['EX_cpd00138_e0'] = -0.021731242 * 4.55 # uptake rate for D-Mannose
|
| 295 |
+
v_prm.lo['EX_cpd00052_e0'] = -0.007307850 * 4.55 # uptake rate for CTP
|
| 296 |
+
v_rfl.lo['EX_cpd00052_e0'] = -0.007307850 * 4.55
|
| 297 |
+
v_prm.lo['EX_cpd00002_e0'] = -0.006289719 * 4.55 # uptake rate for ATP
|
| 298 |
+
v_rfl.lo['EX_cpd00002_e0'] = -0.006289719 * 4.55
|
| 299 |
+
v_prm.lo['EX_cpd00062_e0'] = -0.005932755 * 4.55 # uptake rate for UTP
|
| 300 |
+
v_rfl.lo['EX_cpd00062_e0'] = -0.005932755 * 4.55
|
| 301 |
+
v_rfl.lo['EX_cpd00115_e0'] = -0.001147315 * 4.55 # uptake rate for dATP
|
| 302 |
+
v_rfl.lo['EX_cpd00357_e0'] = -0.001147552 * 4.55 # uptake rate for dTTP
|
| 303 |
+
v_rfl.lo['EX_cpd00241_e0'] = -0.001012678 * 4.55 # uptake rate for dGTP
|
| 304 |
+
v_prm.lo['EX_cpd00356_e0'] = -0.001016235 * 4.55 # uptake rate for dCTP
|
| 305 |
+
v_rfl.lo['EX_cpd00356_e0'] = -0.001016235 * 4.55
|
| 306 |
+
# v_prm.lo['EX_cpd11746_e0'] = -0.320930655 * 4.55 # uptake rate for Cellulose ****
|
| 307 |
+
v_rfl.lo['EX_cpd11746_e0'] = -0.320930655 * 4.55
|
| 308 |
+
v_rfl.lo['EX_cpd29869_e0'] = -0.002499522 * 4.55 # uptake rate for hemicellulose
|
| 309 |
+
# v_prm.lo['EX_cpd00009_e0'] = -0.005244478 * 4.55 # uptake rate for Phosphate, this is an inorganic ion, uptake set to max
|
| 310 |
+
# v_rfl.lo['EX_cpd00009_e0'] = -0.005244478 * 4.55
|
| 311 |
+
v_rfl.lo['EX_cpd00065_e0'] = 0 # uptake rate for Tryptophan
|
| 312 |
+
v_prm.lo['EX_cpd00073_e0'] = -0.629166662 * 4.55 # uptake rate for Urea
|
| 313 |
+
v_rfl.lo['EX_cpd00073_e0'] = -0.629166662 * 4.55
|
| 314 |
+
# v_prm.lo['EX_cpd00048_e0'] = -0.004273279 * 4.55 # uptake rate for Sulfate, this is an inorganic ion, uptake set to max
|
| 315 |
+
# v_rfl.lo['EX_cpd00048_e0'] = -0.004273279 * 4.55
|
| 316 |
+
|
| 317 |
+
# added constraints to bring down the MGK flux
|
| 318 |
+
v_mgk.lo['EX_cpd00162_e0'] = -1 # uptake rate for aminoethanol
|
| 319 |
+
v_mgk.lo['EX_cpd00122_e0'] = -0.01 # uptake rate for n-acetyl-D-glucosamine
|
| 320 |
+
|
| 321 |
+
# added contraints to coorespond to the different treatment options
|
| 322 |
+
|
| 323 |
+
if methane == 'variable':
|
| 324 |
+
if treatment == 'imidazole':
|
| 325 |
+
# reactions that are affected by imidazole treatment
|
| 326 |
+
# Imidazole inhibits lysozyme activity in protozoa, reducing their ability to digest bacteria
|
| 327 |
+
# This reduces predation pressure on bacteria, allowing them to grow more freely
|
| 328 |
+
# We simulate this by increasing biomass production rates and reducing some metabolic constraints
|
| 329 |
+
|
| 330 |
+
# Increase biomass production rates for all bacteria (reduced predation pressure)
|
| 331 |
+
v_mgk.lo['R_biomass0'] = v_mgk.lo['R_biomass0'] * 1.15 # Increase biomass production by 15%
|
| 332 |
+
v_prm.lo['R_biomass0'] = v_prm.lo['R_biomass0'] * 1.15
|
| 333 |
+
v_rfl.lo['R_biomass0'] = v_rfl.lo['R_biomass0'] * 1.15
|
| 334 |
+
# Increase substrate uptake rates (bacteria can access more resources with reduced predation)
|
| 335 |
+
# Note: We'll use more conservative increases and only apply to reactions that exis
|
| 336 |
+
# v_prm.lo['EX_cpd00027_e0'] = v_prm.lo['EX_cpd00027_e0'] * 1.2
|
| 337 |
+
# v_rfl.lo['EX_cpd00027_e0'] = v_rfl.lo['EX_cpd00027_e0'] * 1.2
|
| 338 |
+
# Increase acetate production (common byproduct of bacterial metabolism)
|
| 339 |
+
v_mgk.lo['EX_cpd00029_e0'] = v_mgk.lo['EX_cpd00029_e0'] * 1.1
|
| 340 |
+
v_prm.lo['EX_cpd00029_e0'] = v_prm.lo['EX_cpd00029_e0'] * 1.1
|
| 341 |
+
v_rfl.lo['EX_cpd00029_e0'] = v_rfl.lo['EX_cpd00029_e0'] * 1.1
|
| 342 |
+
# Increase formate production (important for methanogenesis)
|
| 343 |
+
# v_mgk.lo['EX_cpd00056_e0'] = v_mgk.lo['EX_cpd00056_e0'] * 1.2
|
| 344 |
+
# v_prm.lo['EX_cpd00056_e0'] = v_prm.lo['EX_cpd00056_e0'] * 1.2
|
| 345 |
+
# v_rfl.lo['EX_cpd00056_e0'] = v_rfl.lo['EX_cpd00056_e0'] * 1.2
|
| 346 |
+
# Increase H2 production (important substrate for methanogenesis)
|
| 347 |
+
v_mgk.lo['EX_cpd00067_e0'] = v_mgk.lo['EX_cpd00067_e0'] * 1.25
|
| 348 |
+
v_prm.lo['EX_cpd00067_e0'] = v_prm.lo['EX_cpd00067_e0'] * 1.25
|
| 349 |
+
v_rfl.lo['EX_cpd00067_e0'] = v_rfl.lo['EX_cpd00067_e0'] * 1.25
|
| 350 |
+
print("Imidazole treatment selected, setting constraints...")
|
| 351 |
+
elif treatment == 'l-carnitine':
|
| 352 |
+
# reactions that are affected by l-carnitine treatment
|
| 353 |
+
v_mgk.lo['EX_cpd01188_e0'] = -0.009476130618701499 * 0.89 # output rate for lanosterol, 0.87 times the original value becase cholesterol falls
|
| 354 |
+
v_rfl.lo['EX_cpd01188_e0'] = -0.01658854044409092 * 0.89
|
| 355 |
+
print("L-carnitine treatment selected, setting constraints...")
|
| 356 |
+
elif treatment == 'methyl jasmonate':
|
| 357 |
+
print("Methyl jasmonate treatment selected, setting constraints...")
|
| 358 |
+
v_mgk.lo['EX_cpd00129_e0'] = 0.01608686252400516 * 1.23 # output rate for proline, 1.23 times the original value based on Lubyanova paper
|
| 359 |
+
v_prm.lo['EX_cpd00129_e0'] = 0.004029898865569517 * 1.23
|
| 360 |
+
# v_mgk.lo['R_rxn09296_c0'] = 0.0005201736148737044 * 1.4 # H2O2 reduction by thioredoxin, 1.4 times the original value based on Lubyanova paper
|
| 361 |
+
# v_prm.lo['R_rxn09296_c0'] = 71.50423813116777 * 1.4
|
| 362 |
+
# v_rfl.lo['R_rxn09296_c0'] = 316.9770835412888 * 1.4
|
| 363 |
+
# v_prm.lo['R_rxn12638_c0'] = 65.98723846787729 * 1.23 # breakdown of N-glycylproline
|
| 364 |
+
elif treatment == 'propylpyrazine':
|
| 365 |
+
# reactions that are affected by propylpyrazine treatment
|
| 366 |
+
# v_mgk.lo['R_rxn00305_c0'] = 191.07533512418465 * 3.02 # Pck1 expression went up about 3 times after treatment with TMP, should affect GTP and phosphoenolpyruvate
|
| 367 |
+
# v_prm.lo['R_rxn00305_c0'] = 169.79210656337526 * 3.02
|
| 368 |
+
# v_rfl.lo['R_rxn00305_c0'] = 164.67010537093077 * 3.02
|
| 369 |
+
# v_mgk.lo['R_rxn00285_c0'] = 0.0011420124768651806 * 2.14 # Sucla2 expression went up about 2.14 times after treatment with propylpyrazine, should affect succinyl-CoA
|
| 370 |
+
# v_rfl.lo['R_rxn00285_c0'] = 0.012806125516892619 * 2.14
|
| 371 |
+
# v_mgk.lo['R_rxn12510_c0'] = 0.0010308604158823106 * 1.77 # Pank1 expression went up about 1.77 times after treatment with propylpyrazine, should affect phosphorylation of pantothenate
|
| 372 |
+
# v_prm.lo['R_rxn12510_c0'] = 0.008928357454568775 * 1.77
|
| 373 |
+
# v_rfl.lo['R_rxn12510_c0'] = 0.0015697141164147958 * 1.77
|
| 374 |
+
# v_prm.lo['R_rxn00248_c0'] = 167.2035577959039 * 1.93 # Mdh2 went up about 1.93 times after treatment with propylpyrazine, should affect conversion of L-malate to oxaloacetate
|
| 375 |
+
# v_mgk.lo['R_rxn06037_c0'] = -6.170993629588869e-21 * 3.08 # Hadhb expression went up about 3.08 times after treatment with propylpyrazine, should affect conversion of 3-hydroxyacyl-CoA -> 3-oxoacyl-CoA
|
| 376 |
+
# v_prm.lo['R_rxn00799_c0'] = 127.86504315656339 * 2.19 # Fh1 expression went up about 2.19 times after treatment with propylpyrazine, should affect conversion of fumarate to L-malate
|
| 377 |
+
# v_rfl.lo['R_rxn00256_c0'] = 104.25331895829011 * 1.43 # Cs expression went up about 1.43 times after treatment with propylpyrazine, should affect conversion of oxaloacetate to citrate
|
| 378 |
+
v_mgk.lo['R_rxn12512_c0'] = 0.000453718935224341 * 1.17 # Ppcs expression went up about 1.17 times after treatment with propylpyrazine, should affect conversion of phosphopantothenate combination with cysteine
|
| 379 |
+
v_prm.lo['R_rxn12512_c0'] = 0.004463845288178093 * 1.17
|
| 380 |
+
v_rfl.lo['R_rxn12512_c0'] = 0.0007848557326249302 * 1.17
|
| 381 |
+
print("Propylpyrazine treatment selected, setting constraints...")
|
| 382 |
+
elif treatment == 'no':
|
| 383 |
+
# no treatment, no additional constraints
|
| 384 |
+
print("No treatment selected, using default constraints.")
|
| 385 |
+
elif methane == 'fixed':
|
| 386 |
+
if treatment == 'imidazole':
|
| 387 |
+
# reactions that are affected by imidazole treatment
|
| 388 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.74 * 2.5125e-5 # output rate for methane based on USDA data, conversion factor from ml to mmol/gDCW.hr
|
| 389 |
+
print("Imidazole treatment selected, setting constraints...")
|
| 390 |
+
elif treatment == 'l-carnitine':
|
| 391 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.79 * 2.5125e-5
|
| 392 |
+
# reactions that are affected by l-carnitine treatment
|
| 393 |
+
print("L-carnitine treatment selected, setting constraints...")
|
| 394 |
+
elif treatment == 'methyl jasmonate':
|
| 395 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.53 * 2.5125e-5
|
| 396 |
+
print("Methyl jasmonate treatment selected, setting constraints...")
|
| 397 |
+
elif treatment == 'propylpyrazine':
|
| 398 |
+
v_mgk.fx['EX_cpd01024_e0'] = 4.40 * 2.5125e-5
|
| 399 |
+
# reactions that are affected by propylpyrazine treatment
|
| 400 |
+
print("Propylpyrazine treatment selected, setting constraints...")
|
| 401 |
+
elif treatment == 'no':
|
| 402 |
+
# no treatment, no additional constraints
|
| 403 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.40 * 2.5125e-5
|
| 404 |
+
print("No treatment selected, using default constraints.")
|
| 405 |
+
|
| 406 |
+
# Dual variables for bounds
|
| 407 |
+
global muLB_mgk, muUB_mgk, muLB_prm, muUB_prm, muLB_rfl, muUB_rfl
|
| 408 |
+
|
| 409 |
+
muLB_mgk = Variable(container=cowmunity, name="muLB_mgk", domain=j_mgk, description="Dual variables for MGK LB")
|
| 410 |
+
muUB_mgk = Variable(container=cowmunity, name="muUB_mgk", domain=j_mgk, description="Dual variables for MGK UB")
|
| 411 |
+
muLB_prm = Variable(container=cowmunity, name="muLB_prm", domain=j_prm, description="Dual variables for PRM LB")
|
| 412 |
+
muUB_prm = Variable(container=cowmunity, name="muUB_prm", domain=j_prm, description="Dual variables for PRM UB")
|
| 413 |
+
muLB_rfl = Variable(container=cowmunity, name="muLB_rfl", domain=j_rfl, description="Dual variables for RFL LB")
|
| 414 |
+
muUB_rfl = Variable(container=cowmunity, name="muUB_rfl", domain=j_rfl, description="Dual variables for RFL UB")
|
| 415 |
+
|
| 416 |
+
# Set dual variables to positive
|
| 417 |
+
muLB_mgk.lo[j_mgk] = 0
|
| 418 |
+
muUB_mgk.lo[j_mgk] = 0
|
| 419 |
+
muLB_prm.lo[j_prm] = 0
|
| 420 |
+
muUB_prm.lo[j_prm] = 0
|
| 421 |
+
muLB_rfl.lo[j_rfl] = 0
|
| 422 |
+
muUB_rfl.lo[j_rfl] = 0
|
| 423 |
+
|
| 424 |
+
# transfer uptake positive variables for the shared metabolites
|
| 425 |
+
|
| 426 |
+
global trans_CO2_mgk, trans_H2_mgk, trans_formate_mgk, trans_acetate_mgk, trans_d_mannose_mgk, trans_d_fructose_mgk, trans_tetrathionate_mgk, trans_thiosulfate_mgk
|
| 427 |
+
global trans_cellulose_prm, trans_d_glucose_prm, trans_acetate_prm, trans_l_arabinose_prm, trans_biotin_prm, trans_thiamin_prm, trans_octadecenoate_prm, trans_maltoheptaose_prm
|
| 428 |
+
global trans_nitrite_prm, trans_n_acetyl_d_glucosamine_prm, trans_aminoethanol_prm, trans_cobinamide_prm, trans_alanine_prm, trans_leucine_prm, trans_glycine_prm, trans_proline_prm
|
| 429 |
+
global trans_d_galacturonate_rfl, trans_deoxyadenosine_rfl, trans_dephospho_coa_rfl, trans_cobinamide_rfl, trans_alanine_rfl, trans_leucine_rfl, trans_glycine_rfl, trans_proline_rfl, trans_aminoethanol_rfl
|
| 430 |
+
|
| 431 |
+
trans_CO2_mgk = Variable(container=cowmunity, name="trans_CO2_mgk", description="maximum transfer of CO2 to M. Gottschalkii")
|
| 432 |
+
trans_H2_mgk = Variable(container=cowmunity, name="trans_H2_mgk", description="maximum transfer of H2 to M. Gottschalkii")
|
| 433 |
+
trans_formate_mgk = Variable(container=cowmunity, name='trans_formate_mgk', description="maximum transfer of formate to M. Gottschalkii")
|
| 434 |
+
trans_acetate_mgk = Variable(container=cowmunity, name="trans_acetate_mgk", description="maximum transfer of acetate to M. Gottschalkii")
|
| 435 |
+
trans_d_mannose_mgk = Variable(container=cowmunity, name="trans_dmannose_mgk", description="maximum transfer of D-mannose to M. Gottschalkii")
|
| 436 |
+
trans_d_fructose_mgk = Variable(container=cowmunity, name="trans_dfructose_mgk", description="maximum transfer of D-fructose to M. Gottschalkii")
|
| 437 |
+
trans_tetrathionate_mgk = Variable(container=cowmunity, name="trans_tetrathionate_mgk", description="maximum transfer of tetrathionate to M. Gottschalkii")
|
| 438 |
+
trans_thiosulfate_mgk = Variable(container=cowmunity, name="trans_thiosulfate_mgk", description="maximum transfer of thiosulfate to M. Gottschalkii")
|
| 439 |
+
|
| 440 |
+
trans_cellulose_prm = Variable(container=cowmunity, name='trans_cellulose_prm', description="maximum transfer of cellulose to P. ruminicola")
|
| 441 |
+
trans_d_glucose_prm = Variable(container=cowmunity, name='trans_d_glucose_prm', description="maximum transfer of D-Glucose to P. ruminicola")
|
| 442 |
+
trans_acetate_prm = Variable(container=cowmunity, name='trans_acetate_prm', description="maximum transfer of Acetate to P. ruminicola")
|
| 443 |
+
trans_l_arabinose_prm = Variable(container=cowmunity, name='trans_l_arabinose_prm', description="maximum transfer of L-Arabinose to P. ruminicola")
|
| 444 |
+
trans_biotin_prm = Variable(container=cowmunity, name='trans_biotin_prm', description="maximum transfer of Biotin to P. ruminicola")
|
| 445 |
+
trans_thiamin_prm = Variable(container=cowmunity, name='trans_thiamin_prm', description="maximum transfer of Thiamin to P. ruminicola")
|
| 446 |
+
trans_octadecenoate_prm = Variable(container=cowmunity, name='trans_octadecenoate_prm', description="maximum transfer of octadecenoate to P. ruminicola")
|
| 447 |
+
trans_maltoheptaose_prm = Variable(container=cowmunity, name='trans_maltoheptaose_prm', description="maximum transfer of Maltoheptaose to P. ruminicola")
|
| 448 |
+
trans_nitrite_prm = Variable(container=cowmunity, name='trans_nitrite_prm', description="maximum transfer of Nitrite to P. ruminicola")
|
| 449 |
+
trans_n_acetyl_d_glucosamine_prm = Variable(container=cowmunity, name='trans_n_acetyl_d_glucosamine_prm', description="maximum transfer of N-Acetyl-D-glucosamine to P. ruminicola")
|
| 450 |
+
trans_aminoethanol_prm = Variable(container=cowmunity, name='trans_aminoethanol_prm', description="maximum transfer of Aminoethanol to P. ruminicola")
|
| 451 |
+
trans_cobinamide_prm = Variable(container=cowmunity, name='trans_cobinamide_prm', description="maximum transfer of Cobinamide to P. ruminicola")
|
| 452 |
+
trans_alanine_prm = Variable(container=cowmunity, name='trans_alanine_prm', description="maximum transfer of Alanine to P. ruminicola")
|
| 453 |
+
trans_leucine_prm = Variable(container=cowmunity, name='trans_leucine_prm', description="maximum transfer of Leucine to P. ruminicola")
|
| 454 |
+
trans_glycine_prm = Variable(container=cowmunity, name='trans_glycine_prm', description="maximum transfer of Glycine to P. ruminicola")
|
| 455 |
+
trans_proline_prm = Variable(container=cowmunity, name='trans_proline_prm', description="maximum transfer of Proline to P. ruminicola")
|
| 456 |
+
|
| 457 |
+
trans_d_galacturonate_rfl = Variable(container=cowmunity, name='trans_d_galacturonate_rfl', description="maximum transfer of D-Galacturonate to R. flavefaciens")
|
| 458 |
+
trans_deoxyadenosine_rfl = Variable(container=cowmunity, name='trans_deoxyadenosine_rfl', description="maximum transfer of Deoxyadenosine to R. flavefaciens")
|
| 459 |
+
trans_dephospho_coa_rfl = Variable(container=cowmunity, name='trans_dephospho_coa_rfl', description="maximum transfer of Dephospho-CoA to R. flavefaciens")
|
| 460 |
+
trans_cobinamide_rfl = Variable(container=cowmunity, name='trans_cobinamide_rfl', description="maximum transfer of Cobinamide to R. flavefaciens")
|
| 461 |
+
trans_alanine_rfl = Variable(container=cowmunity, name='trans_alanine_rfl', description="maximum transfer of Alanine to R. flavefaciens")
|
| 462 |
+
trans_leucine_rfl = Variable(container=cowmunity, name='trans_leucine_rfl', description="maximum transfer of Leucine to R. flavefaciens")
|
| 463 |
+
trans_glycine_rfl = Variable(container=cowmunity, name='trans_glycine_rfl', description="maximum transfer of Glycine to R. flavefaciens")
|
| 464 |
+
trans_proline_rfl = Variable(container=cowmunity, name='trans_proline_rfl', description="maximum transfer of Proline to R. flavefaciens")
|
| 465 |
+
trans_aminoethanol_rfl = Variable(container=cowmunity, name='trans_aminoethanol_rfl', description="maximum transfer of Aminoethanol to R. flavefaciens")
|
| 466 |
+
|
| 467 |
+
# set the transfer variables to positive, these are the maximum transfer rates for each metabolite
|
| 468 |
+
|
| 469 |
+
trans_CO2_mgk.lo = 0
|
| 470 |
+
trans_H2_mgk.lo = 0
|
| 471 |
+
trans_formate_mgk.lo = 0
|
| 472 |
+
trans_acetate_mgk.lo = 0
|
| 473 |
+
trans_d_mannose_mgk.lo = 0
|
| 474 |
+
trans_d_fructose_mgk.lo = 0
|
| 475 |
+
trans_tetrathionate_mgk.lo = 0
|
| 476 |
+
trans_thiosulfate_mgk.lo = 0
|
| 477 |
+
|
| 478 |
+
trans_cellulose_prm.lo = 0
|
| 479 |
+
trans_d_glucose_prm.lo = 0
|
| 480 |
+
trans_acetate_prm.lo = 0
|
| 481 |
+
trans_l_arabinose_prm.lo = 0
|
| 482 |
+
trans_biotin_prm.lo = 0
|
| 483 |
+
trans_thiamin_prm.lo = 0
|
| 484 |
+
trans_octadecenoate_prm.lo = 0
|
| 485 |
+
trans_maltoheptaose_prm.lo = 0
|
| 486 |
+
trans_nitrite_prm.lo = 0
|
| 487 |
+
trans_n_acetyl_d_glucosamine_prm.lo = 0
|
| 488 |
+
trans_aminoethanol_prm.lo = 0
|
| 489 |
+
trans_cobinamide_prm.lo = 0
|
| 490 |
+
trans_alanine_prm.lo = 0
|
| 491 |
+
trans_leucine_prm.lo = 0
|
| 492 |
+
trans_glycine_prm.lo = 0
|
| 493 |
+
trans_proline_prm.lo = 0
|
| 494 |
+
|
| 495 |
+
trans_d_galacturonate_rfl.lo = 0
|
| 496 |
+
trans_deoxyadenosine_rfl.lo = 0
|
| 497 |
+
trans_dephospho_coa_rfl.lo = 0
|
| 498 |
+
trans_cobinamide_rfl.lo = 0
|
| 499 |
+
trans_alanine_rfl.lo = 0
|
| 500 |
+
trans_leucine_rfl.lo = 0
|
| 501 |
+
trans_glycine_rfl.lo = 0
|
| 502 |
+
trans_proline_rfl.lo = 0
|
| 503 |
+
trans_aminoethanol_rfl.lo = 0
|
| 504 |
+
|
| 505 |
+
def Equations():
|
| 506 |
+
print("Adding equations...")
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
# Objective Functions (Outer Objective)
|
| 510 |
+
biomass_objective = Equation(container=cowmunity, name="biomass_objective", description="Objective function for total biomass accumulation")
|
| 511 |
+
biomass_objective[...] = biomass_outer == v_mgk['R_biomass0'] + v_prm['R_biomass0'] + v_rfl['R_biomass0']
|
| 512 |
+
|
| 513 |
+
ATP_objective = Equation(container=cowmunity, name="ATP_objective", description="Objective function for total ATP Production")
|
| 514 |
+
ATP_objective[...] = ATP_outer == v_mgk['R_rxn02831_c0'] + v_mgk['R_rxn03535_c0'] + v_mgk['R_rxn06874_c0'] + v_mgk['R_rxn10476_c0'] + v_mgk['R_rxn11544_c0'] \
|
| 515 |
+
+ v_prm['R_rxn00986_c0'] + v_prm['R_rxn01987_c0'] + v_prm['R_rxn10042_c0'] \
|
| 516 |
+
+ v_rfl['R_rxn05840_c0'] + v_rfl['R_rxn06428_c0'] + v_rfl['R_rxn06874_c0'] + v_rfl['R_rxn10042_c0']
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
# Constraints
|
| 520 |
+
# these are the things that are going to make the model into a true community model rather than three separate models
|
| 521 |
+
|
| 522 |
+
trans_CO2_mgk_balance = Equation(container=cowmunity, name='trans_CO2_balance', description="Balance for CO2 transfer to M. Gottschalkii")
|
| 523 |
+
trans_CO2_mgk_balance[...] = trans_CO2_mgk <= v_prm['EX_cpd00011_e0'] + v_rfl['EX_cpd00011_e0']
|
| 524 |
+
|
| 525 |
+
trans_H2_mgk_balance = Equation(container=cowmunity, name= 'trans_H2_mgk_balance', description="Balance for H2 transfer to M. Gottschalkii")
|
| 526 |
+
trans_H2_mgk_balance[...] = trans_H2_mgk <= v_prm['EX_cpd11640_e0'] + v_rfl['EX_cpd11640_e0']
|
| 527 |
+
|
| 528 |
+
trans_formate_mgk_balance = Equation(container=cowmunity, name='trans_formate_mgk_balance', description="Balance for formate transfer to M. Gottschalkii")
|
| 529 |
+
trans_formate_mgk_balance[...] = trans_formate_mgk <= v_prm['EX_cpd00047_e0'] + v_rfl['EX_cpd00047_e0']
|
| 530 |
+
|
| 531 |
+
trans_acetate_mgk_balance = Equation(container=cowmunity, name='trans_acetate_mgk_balance', description="Balance for acetate transfer to M. Gottschalkii")
|
| 532 |
+
trans_acetate_mgk_balance[...] = trans_acetate_mgk <= v_rfl['EX_cpd00029_e0']
|
| 533 |
+
|
| 534 |
+
trans_d_mannose_mgk_balance = Equation(container=cowmunity, name='trans_d_mannose_mgk_balance', description="Balance for D-mannose transfer to M. Gottschalkii")
|
| 535 |
+
trans_d_mannose_mgk_balance[...] = trans_d_mannose_mgk <= v_rfl['EX_cpd00138_e0']
|
| 536 |
+
|
| 537 |
+
trans_d_fructose_mgk_balance = Equation(container=cowmunity, name='trans_d_fructose_mgk_balance', description="Balance for D-fructose transfer to M. Gottschalkii")
|
| 538 |
+
trans_d_fructose_mgk_balance[...] = trans_d_fructose_mgk <= v_rfl['EX_cpd00082_e0']
|
| 539 |
+
|
| 540 |
+
trans_tetrathionate_mgk_balance = Equation(container=cowmunity, name='trans_tetrathionate_mgk_balance', description="Balance for tetrathionate transfer to M. Gottschalkii")
|
| 541 |
+
trans_tetrathionate_mgk_balance[...] = trans_tetrathionate_mgk <= v_rfl['EX_cpd01414_e0']
|
| 542 |
+
|
| 543 |
+
trans_thiosulfate_mgk_balance = Equation(container=cowmunity, name='trans_thiosulfate_mgk_balance', description="Balance for thiosulfate transfer to M. Gottschalkii")
|
| 544 |
+
trans_thiosulfate_mgk_balance[...] = trans_thiosulfate_mgk <= v_prm['EX_cpd00268_e0']
|
| 545 |
+
|
| 546 |
+
trans_cellulose_prm_balance = Equation(container=cowmunity, name='trans_cellulose_prm_balance', description="Balance for cellulose transfer to P. ruminicola")
|
| 547 |
+
trans_cellulose_prm_balance[...] = trans_cellulose_prm <= v_rfl['EX_cpd11746_e0']
|
| 548 |
+
|
| 549 |
+
trans_d_glucose_prm_balance = Equation(container=cowmunity, name='trans_d_glucose_prm_balance', description="Balance for D-glucose transfer to P. ruminicola")
|
| 550 |
+
trans_d_glucose_prm_balance[...] = trans_d_glucose_prm <= v_rfl['EX_cpd00027_e0']
|
| 551 |
+
|
| 552 |
+
trans_acetate_prm_balance = Equation(container=cowmunity, name='trans_acetate_prm_balance', description="Balance for acetate transfer to P. ruminicola")
|
| 553 |
+
trans_acetate_prm_balance[...] = trans_acetate_prm <= v_rfl['EX_cpd00029_e0']
|
| 554 |
+
|
| 555 |
+
trans_l_arabinose_prm_balance = Equation(container=cowmunity, name='trans_l_arabinose_prm_balance', description="Balance for L-arabinose transfer to P. ruminicola")
|
| 556 |
+
trans_l_arabinose_prm_balance[...] = trans_l_arabinose_prm <= v_rfl['EX_cpd00224_e0']
|
| 557 |
+
|
| 558 |
+
trans_biotin_prm_balance = Equation(container=cowmunity, name='trans_biotin_prm_balance', description="Balance for biotin transfer to P. ruminicola")
|
| 559 |
+
trans_biotin_prm_balance[...] = trans_biotin_prm <= v_rfl['EX_cpd00104_e0']
|
| 560 |
+
|
| 561 |
+
# ****** commented to preserve RFL FLux ********* trans_thiamin_prm_balance = Equation(container=cowmunity, name='trans_thiamin_prm_balance', description="Balance for thiamin transfer to P. ruminicola")
|
| 562 |
+
# ****** commented to preserve RFL FLux ********* trans_thiamin_prm_balance[...] = trans_thiamin_prm <= v_rfl['EX_cpd00305_e0']
|
| 563 |
+
|
| 564 |
+
trans_octadecenoate_prm_balance = Equation(container=cowmunity, name='trans_octadecenoate_prm_balance', description="Balance for octadecenoate transfer to P. ruminicola")
|
| 565 |
+
trans_octadecenoate_prm_balance[...] = trans_octadecenoate_prm <= v_rfl['EX_cpd15269_e0'] + v_mgk['EX_cpd15269_e0']
|
| 566 |
+
|
| 567 |
+
trans_maltoheptaose_prm_balance = Equation(container=cowmunity, name='trans_maltoheptaose_prm_balance', description="Balance for maltoheptaose transfer to P. ruminicola")
|
| 568 |
+
trans_maltoheptaose_prm_balance[...] = trans_maltoheptaose_prm <= v_rfl['EX_cpd15494_e0']
|
| 569 |
+
|
| 570 |
+
trans_nitrite_prm_balance = Equation(container=cowmunity, name='trans_nitrite_prm_balance', description="Balance for nitrite transfer to P. ruminicola")
|
| 571 |
+
trans_nitrite_prm_balance[...] = trans_nitrite_prm <= v_mgk['EX_cpd00075_e0']
|
| 572 |
+
|
| 573 |
+
# ****** commented to preserve MGK FLux ********* trans_n_acetyl_d_glucosamine_prm_balance = Equation(container=cowmunity, name='trans_n_acetyl_d_glucosamine_prm_balance', description="Balance for N-acetyl-D-glucosamine transfer to P. ruminicola")
|
| 574 |
+
# ****** commented to preserve MGK FLux ********* trans_n_acetyl_d_glucosamine_prm_balance[...] = trans_n_acetyl_d_glucosamine_prm <= v_mgk['EX_cpd00122_e0']
|
| 575 |
+
|
| 576 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_prm_balance = Equation(container=cowmunity, name='trans_aminoethanol_prm_balance', description="Balance for aminoethanol transfer to P. ruminicola")
|
| 577 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_prm_balance[...] = trans_aminoethanol_prm <= v_mgk['EX_cpd00162_e0']
|
| 578 |
+
|
| 579 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_prm_balance = Equation(container=cowmunity, name='trans_cobinamide_prm_balance', description="Balance for cobinamide transfer to P. ruminicola")
|
| 580 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_prm_balance[...] = trans_cobinamide_prm <= v_mgk['EX_cpd03422_e0']
|
| 581 |
+
|
| 582 |
+
trans_alanine_prm_balance = Equation(container=cowmunity, name='trans_alanine_prm_balance', description="Balance for alanine transfer to P. ruminicola")
|
| 583 |
+
trans_alanine_prm_balance[...] = trans_alanine_prm <= v_mgk['EX_cpd00035_e0']
|
| 584 |
+
|
| 585 |
+
trans_leucine_prm_balance = Equation(container=cowmunity, name='trans_leucine_prm_balance', description="Balance for leucine transfer to P. ruminicola")
|
| 586 |
+
trans_leucine_prm_balance[...] = trans_leucine_prm <= v_mgk['EX_cpd00107_e0']
|
| 587 |
+
|
| 588 |
+
trans_glycine_prm_balance = Equation(container=cowmunity, name='trans_glycine_prm_balance', description="Balance for glycine transfer to P. ruminicola")
|
| 589 |
+
trans_glycine_prm_balance[...] = trans_glycine_prm <= v_mgk['EX_cpd00033_e0']
|
| 590 |
+
|
| 591 |
+
trans_proline_prm_balance = Equation(container=cowmunity, name='trans_proline_prm_balance', description="Balance for proline transfer to P. ruminicola")
|
| 592 |
+
trans_proline_prm_balance[...] = trans_proline_prm <= v_mgk['EX_cpd00129_e0']
|
| 593 |
+
|
| 594 |
+
trans_d_galacturonate_rfl_balance = Equation(container=cowmunity, name='trans_d_galacturonate_rfl_balance', description="Balance for D-galacturonate transfer to R. flavefaciens")
|
| 595 |
+
trans_d_galacturonate_rfl_balance[...] = trans_d_galacturonate_rfl <= v_prm['EX_cpd00280_e0']
|
| 596 |
+
|
| 597 |
+
trans_deoxyadenosine_rfl_balance = Equation(container=cowmunity, name='trans_deoxyadenosine_rfl_balance', description="Balance for deoxyadenosine transfer to R. flavefaciens")
|
| 598 |
+
trans_deoxyadenosine_rfl_balance[...] = trans_deoxyadenosine_rfl <= v_prm['EX_cpd00438_e0']
|
| 599 |
+
|
| 600 |
+
trans_dephospho_coa_rfl_balance = Equation(container=cowmunity, name='trans_dephospho_coa_rfl_balance', description="Balance for dephospho-CoA transfer to R. flavefaciens")
|
| 601 |
+
trans_dephospho_coa_rfl_balance[...] = trans_dephospho_coa_rfl <= v_mgk['EX_cpd00655_e0']
|
| 602 |
+
|
| 603 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_rfl_balance = Equation(container=cowmunity, name='trans_cobinamide_rfl_balance', description="Balance for cobinamide transfer to R. flavefaciens")
|
| 604 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_rfl_balance[...] = trans_cobinamide_rfl <= v_mgk['EX_cpd03422_e0']
|
| 605 |
+
|
| 606 |
+
trans_alanine_rfl_balance = Equation(container=cowmunity, name='trans_alanine_rfl_balance', description="Balance for alanine transfer to R. flavefaciens")
|
| 607 |
+
trans_alanine_rfl_balance[...] = trans_alanine_rfl <= v_mgk['EX_cpd00035_e0']
|
| 608 |
+
|
| 609 |
+
trans_leucine_rfl_balance = Equation(container=cowmunity, name='trans_leucine_rfl_balance', description="Balance for leucine transfer to R. flavefaciens")
|
| 610 |
+
trans_leucine_rfl_balance[...] = trans_leucine_rfl <= v_mgk['EX_cpd00107_e0']
|
| 611 |
+
|
| 612 |
+
trans_glycine_rfl_balance = Equation(container=cowmunity, name='trans_glycine_rfl_balance', description="Balance for glycine transfer to R. flavefaciens")
|
| 613 |
+
trans_glycine_rfl_balance[...] = trans_glycine_rfl <= v_mgk['EX_cpd00033_e0']
|
| 614 |
+
|
| 615 |
+
# ****** commented to preserve RFL FLux ********* trans_proline_rfl_balance = Equation(container=cowmunity, name='trans_proline_rfl_balance', description="Balance for proline transfer to R. flavefaciens")
|
| 616 |
+
# ****** commented to preserve RFL FLux ********* trans_proline_rfl_balance[...] = trans_proline_rfl <= v_mgk['EX_cpd00129_e0']
|
| 617 |
+
|
| 618 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_rfl_balance = Equation(container=cowmunity, name='trans_aminoethanol_rfl_balance', description="Balance for aminoethanol transfer to R. flavefaciens")
|
| 619 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_rfl_balance[...] = trans_aminoethanol_rfl <= v_mgk['EX_cpd00162_e0']
|
| 620 |
+
|
| 621 |
+
# ****** commented to preserve MGK FLux ********* overall_cobinamide_balance = Equation(container=cowmunity, name='overall_cobinamide_balance', description='Balance for cobinamide transfer for both prm and rfl')
|
| 622 |
+
# ****** commented to preserve MGK FLux ********* overall_cobinamide_balance[...] = trans_cobinamide_prm + trans_cobinamide_rfl <= v_mgk['EX_cpd03422_e0']
|
| 623 |
+
|
| 624 |
+
overall_alanine_balance = Equation(container=cowmunity, name='overall_alanine_balance', description='Balance for alanine transfer for both prm and rfl')
|
| 625 |
+
overall_alanine_balance[...] = trans_alanine_prm + trans_alanine_rfl <= v_mgk['EX_cpd00035_e0']
|
| 626 |
+
|
| 627 |
+
overall_leucine_balance = Equation(container=cowmunity, name='overall_leucine_balance', description='Balance for leucine transfer for both prm and rfl')
|
| 628 |
+
overall_leucine_balance[...] = trans_leucine_prm + trans_leucine_rfl <= v_mgk['EX_cpd00107_e0']
|
| 629 |
+
|
| 630 |
+
overall_glycine_balance = Equation(container=cowmunity, name='overall_glycine_balance', description='Balance for glycine transfer for both prm and rfl')
|
| 631 |
+
overall_glycine_balance[...] = trans_glycine_prm + trans_glycine_rfl <= v_mgk['EX_cpd00033_e0']
|
| 632 |
+
|
| 633 |
+
overall_proline_balance = Equation(container=cowmunity, name='overall_proline_balance', description='Balance for proline transfer for both prm and rfl')
|
| 634 |
+
overall_proline_balance[...] = trans_proline_prm + trans_proline_rfl <= v_mgk['EX_cpd00129_e0']
|
| 635 |
+
|
| 636 |
+
# ****** commented to preserve MGK FLux ********* overall_aminoethanol_balance = Equation(container=cowmunity, name='overall_aminoethanol_balance', description='Balance for aminoethanol transfer for both prm and rfl')
|
| 637 |
+
# ****** commented to preserve MGK FLux ********* overall_aminoethanol_balance[...] = trans_aminoethanol_prm + trans_aminoethanol_rfl <= v_mgk['EX_cpd00162_e0']
|
| 638 |
+
|
| 639 |
+
# adding the constraints to each model
|
| 640 |
+
|
| 641 |
+
constraint_CO2_mgk = Equation(container=cowmunity, name="constraint_CO2_mgk", description="constraint for the uptake of CO2 to M. Gottschalkii")
|
| 642 |
+
constraint_CO2_mgk[...] = trans_CO2_mgk == v_mgk['EX_cpd00011_e0']
|
| 643 |
+
|
| 644 |
+
constraint_H2_mgk = Equation(container=cowmunity, name="constraint_H2_mgk", description="constraint for the uptake of H2 to M. Gottschalkii")
|
| 645 |
+
constraint_H2_mgk[...] = trans_H2_mgk == v_mgk['EX_cpd11640_e0']
|
| 646 |
+
|
| 647 |
+
constraint_formate_mgk = Equation(container=cowmunity, name='constraint_formate_mgk', description="constraint for the uptake of formate to M. Gottschalkii")
|
| 648 |
+
constraint_formate_mgk[...] = trans_formate_mgk == v_mgk['EX_cpd00047_e0']
|
| 649 |
+
|
| 650 |
+
constraint_acetate_mgk = Equation(container=cowmunity, name="constraint_acetate_mgk", description="constraint for the uptake of acetate to M. Gottschalkii")
|
| 651 |
+
constraint_acetate_mgk[...] = trans_acetate_mgk == v_mgk['EX_cpd00029_e0']
|
| 652 |
+
|
| 653 |
+
constraint_d_mannose_mgk = Equation(container=cowmunity, name="constraint_dmannose_mgk", description="constraint for the uptake of D-mannose to M. Gottschalkii")
|
| 654 |
+
constraint_d_mannose_mgk[...] = trans_d_mannose_mgk == v_mgk['EX_cpd00138_e0']
|
| 655 |
+
|
| 656 |
+
constraint_d_fructose_mgk = Equation(container=cowmunity, name="constraint_dfructose_mgk", description="constraint for the uptake of D-fructose to M. Gottschalkii")
|
| 657 |
+
constraint_d_fructose_mgk[...] = trans_d_fructose_mgk == v_mgk['EX_cpd00082_e0']
|
| 658 |
+
|
| 659 |
+
constraint_tetrathionate_mgk = Equation(container=cowmunity, name="constraint_tetrathionate_mgk", description="constraint for the uptake of tetrathionate to M. Gottschalkii")
|
| 660 |
+
constraint_tetrathionate_mgk[...] = trans_tetrathionate_mgk == v_mgk['EX_cpd01414_e0']
|
| 661 |
+
|
| 662 |
+
constraint_thiosulfate_mgk = Equation(container=cowmunity, name="constraint_thiosulfate_mgk", description="constraint for the uptake of thiosulfate to M. Gottschalkii")
|
| 663 |
+
constraint_thiosulfate_mgk[...] = trans_thiosulfate_mgk == v_mgk['EX_cpd00268_e0']
|
| 664 |
+
|
| 665 |
+
constraint_cellulose_prm = Equation(container=cowmunity, name='constraint_cellulose_prm', description="constraint for the uptake of cellulose to P. ruminicola")
|
| 666 |
+
constraint_cellulose_prm[...] = trans_cellulose_prm == v_prm['EX_cpd11746_e0']
|
| 667 |
+
|
| 668 |
+
constraint_d_glucose_prm = Equation(container=cowmunity, name='constraint_d_glucose_prm', description="constraint for the uptake of D-Glucose to P. ruminicola")
|
| 669 |
+
constraint_d_glucose_prm[...] = trans_d_glucose_prm == v_prm['EX_cpd00027_e0']
|
| 670 |
+
|
| 671 |
+
constraint_acetate_prm = Equation(container=cowmunity, name='constraint_acetate_prm', description="constraint for the uptake of Acetate to P. ruminicola")
|
| 672 |
+
constraint_acetate_prm[...] = trans_acetate_prm == v_prm['EX_cpd00029_e0']
|
| 673 |
+
|
| 674 |
+
constraint_l_arabinose_prm = Equation(container=cowmunity, name='constraint_l_arabinose_prm', description="constraint for the uptake of L-Arabinose to P. ruminicola")
|
| 675 |
+
constraint_l_arabinose_prm[...] = trans_l_arabinose_prm == v_prm['EX_cpd00224_e0']
|
| 676 |
+
|
| 677 |
+
constraint_biotin_prm = Equation(container=cowmunity, name='constraint_biotin_prm', description="constraint for the uptake of Biotin to P. ruminicola")
|
| 678 |
+
constraint_biotin_prm[...] = trans_biotin_prm == v_prm['EX_cpd00104_e0']
|
| 679 |
+
|
| 680 |
+
# ****** commented to preserve RFL FLux ********* constraint_thiamin_prm = Equation(container=cowmunity, name='constraint_thiamin_prm', description="constraint for the uptake of Thiamin to P. ruminicola")
|
| 681 |
+
# ****** commented to preserve RFL FLux ********* constraint_thiamin_prm[...] = trans_thiamin_prm == v_prm['EX_cpd00305_e0']
|
| 682 |
+
|
| 683 |
+
constraint_octadecenoate_prm = Equation(container=cowmunity, name='constraint_octadecenoate_prm', description="constraint for the uptake of octadecenoate to P. ruminicola")
|
| 684 |
+
constraint_octadecenoate_prm[...] = trans_octadecenoate_prm == v_prm['EX_cpd15269_e0']
|
| 685 |
+
|
| 686 |
+
constraint_maltoheptaose_prm = Equation(container=cowmunity, name='constraint_maltoheptaose_prm', description="constraint for the uptake of Maltoheptaose to P. ruminicola")
|
| 687 |
+
constraint_maltoheptaose_prm[...] = trans_maltoheptaose_prm == v_prm['EX_cpd15494_e0']
|
| 688 |
+
|
| 689 |
+
constraint_nitrite_prm = Equation(container=cowmunity, name='constraint_nitrite_prm', description="constraint for the uptake of Nitrite to P. ruminicola")
|
| 690 |
+
constraint_nitrite_prm[...] = trans_nitrite_prm == v_prm['EX_cpd00075_e0']
|
| 691 |
+
|
| 692 |
+
# ****** commented to preserve MGK FLux ********* constraint_n_acetyl_d_glucosamine_prm = Equation(container=cowmunity, name='constraint_n_acetyl_d_glucosamine_prm', description="constraint for the uptake of N-Acetyl-D-glucosamine to P. ruminicola")
|
| 693 |
+
# ****** commented to preserve MGK FLux ********* constraint_n_acetyl_d_glucosamine_prm[...] = trans_n_acetyl_d_glucosamine_prm == v_prm['EX_cpd00122_e0']
|
| 694 |
+
|
| 695 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_prm = Equation(container=cowmunity, name='constraint_aminoethanol_prm', description="constraint for the uptake of Aminoethanol to P. ruminicola")
|
| 696 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_prm[...] = trans_aminoethanol_prm == v_prm['EX_cpd00162_e0']
|
| 697 |
+
|
| 698 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_prm = Equation(container=cowmunity, name='constraint_cobinamide_prm', description="constraint for the uptake of Cobinamide to P. ruminicola")
|
| 699 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_prm[...] = trans_cobinamide_prm == v_prm['EX_cpd03422_e0']
|
| 700 |
+
|
| 701 |
+
constraint_alanine_prm = Equation(container=cowmunity, name='constraint_alanine_prm', description="constraint for the uptake of Alanine to P. ruminicola")
|
| 702 |
+
constraint_alanine_prm[...] = trans_alanine_prm == v_prm['EX_cpd00035_e0']
|
| 703 |
+
|
| 704 |
+
constraint_leucine_prm = Equation(container=cowmunity, name='constraint_leucine_prm', description="constraint for the uptake of Leucine to P. ruminicola")
|
| 705 |
+
constraint_leucine_prm[...] = trans_leucine_prm == v_prm['EX_cpd00107_e0']
|
| 706 |
+
|
| 707 |
+
constraint_glycine_prm = Equation(container=cowmunity, name='constraint_glycine_prm', description="constraint for the uptake of Glycine to P. ruminicola")
|
| 708 |
+
constraint_glycine_prm[...] = trans_glycine_prm == v_prm['EX_cpd00033_e0']
|
| 709 |
+
|
| 710 |
+
constraint_proline_prm = Equation(container=cowmunity, name='constraint_proline_prm', description="constraint for the uptake of Proline to P. ruminicola")
|
| 711 |
+
constraint_proline_prm[...] = trans_proline_prm == v_prm['EX_cpd00129_e0']
|
| 712 |
+
|
| 713 |
+
constraint_d_galacturonate_rfl = Equation(container=cowmunity, name='constraint_d_galacturonate_rfl', description="constraint for the uptake of D-Galacturonate to R. flavefaciens")
|
| 714 |
+
constraint_d_galacturonate_rfl[...] = trans_d_galacturonate_rfl == v_rfl['EX_cpd00280_e0']
|
| 715 |
+
|
| 716 |
+
constraint_deoxyadenosine_rfl = Equation(container=cowmunity, name='constraint_deoxyadenosine_rfl', description="constraint for the uptake of Deoxyadenosine to R. flavefaciens")
|
| 717 |
+
constraint_deoxyadenosine_rfl[...] = trans_deoxyadenosine_rfl == v_rfl['EX_cpd00438_e0']
|
| 718 |
+
|
| 719 |
+
constraint_dephospho_coa_rfl = Equation(container=cowmunity, name='constraint_dephospho_coa_rfl', description="constraint for the uptake of Dephospho-CoA to R. flavefaciens")
|
| 720 |
+
constraint_dephospho_coa_rfl[...] = trans_dephospho_coa_rfl == v_rfl['EX_cpd00655_e0']
|
| 721 |
+
|
| 722 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_rfl = Equation(container=cowmunity, name='constraint_cobinamide_rfl', description="constraint for the uptake of Cobinamide to R. flavefaciens")
|
| 723 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_rfl[...] = trans_cobinamide_rfl == v_rfl['EX_cpd03422_e0']
|
| 724 |
+
|
| 725 |
+
constraint_alanine_rfl = Equation(container=cowmunity, name='constraint_alanine_rfl', description="constraint for the uptake of Alanine to R. flavefaciens")
|
| 726 |
+
constraint_alanine_rfl[...] = trans_alanine_rfl == v_rfl['EX_cpd00035_e0']
|
| 727 |
+
|
| 728 |
+
constraint_leucine_rfl = Equation(container=cowmunity, name='constraint_leucine_rfl', description="constraint for the uptake of Leucine to R. flavefaciens")
|
| 729 |
+
constraint_leucine_rfl[...] = trans_leucine_rfl == v_rfl['EX_cpd00107_e0']
|
| 730 |
+
|
| 731 |
+
constraint_glycine_rfl = Equation(container=cowmunity, name='constraint_glycine_rfl', description="constraint for the uptake of Glycine to R. flavefaciens")
|
| 732 |
+
constraint_glycine_rfl[...] = trans_glycine_rfl == v_rfl['EX_cpd00033_e0']
|
| 733 |
+
|
| 734 |
+
# ****** commented to preserve RFL FLux ********* constraint_proline_rfl = Equation(container=cowmunity, name='constraint_proline_rfl', description="constraint for the uptake of Proline to R. flavefaciens")
|
| 735 |
+
# ****** commented to preserve RFL FLux ********* constraint_proline_rfl[...] = trans_proline_rfl == v_rfl['EX_cpd00129_e0']
|
| 736 |
+
|
| 737 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_rfl = Equation(container=cowmunity, name='constraint_aminoethanol_rfl', description="constraint for the uptake of Aminoethanol to R. flavefaciens")
|
| 738 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_rfl[...] = trans_aminoethanol_rfl == v_rfl['EX_cpd00162_e0']
|
| 739 |
+
|
| 740 |
+
# mass balance equations
|
| 741 |
+
|
| 742 |
+
mgk_mass_balance = Equation(container=cowmunity, name='mgk_mass_balance', domain=i_mgk, description='overall mass balance for mgk')
|
| 743 |
+
mgk_mass_balance[i_mgk] = Sum(j_mgk, S_mgk[j_mgk, i_mgk] * v_mgk[j_mgk]) == 0
|
| 744 |
+
|
| 745 |
+
prm_mass_balance = Equation(container=cowmunity, name='prm_mass_balance', domain=i_prm, description='overall mass balance for prm')
|
| 746 |
+
prm_mass_balance[i_prm] = Sum(j_prm, S_prm[j_prm, i_prm] * v_prm[j_prm]) == 0
|
| 747 |
+
|
| 748 |
+
rfl_mass_balance = Equation(container=cowmunity, name='rfl_mass_balance', domain=i_rfl, description='overall mass balance for rfl')
|
| 749 |
+
rfl_mass_balance[i_rfl] = Sum(j_rfl, S_rfl[j_rfl, i_rfl] * v_rfl[j_rfl]) == 0
|
| 750 |
+
|
| 751 |
+
# dual problem constraint equations
|
| 752 |
+
|
| 753 |
+
mgk_dual_constraint = Equation(container=cowmunity, name="mgk_dual_constraint", domain=j_mgk, description="Dual constraint for MGK")
|
| 754 |
+
mgk_dual_constraint[j_mgk] = Sum(i_mgk, lambda_mgk[i_mgk] * S_mgk[j_mgk, i_mgk]) + \
|
| 755 |
+
muUB_mgk[j_mgk] - muLB_mgk[j_mgk] == 0
|
| 756 |
+
|
| 757 |
+
prm_dual_constraint = Equation(container=cowmunity, name="prm_dual_constraint", domain=j_prm, description="Dual constraint for PRM")
|
| 758 |
+
prm_dual_constraint[j_prm] = Sum(i_prm, lambda_prm[i_prm] * S_prm[j_prm, i_prm]) + \
|
| 759 |
+
muUB_prm[j_prm] - muLB_prm[j_prm] == 0
|
| 760 |
+
|
| 761 |
+
rfl_dual_constraint = Equation(container=cowmunity, name="rfl_dual_constraint", domain=j_rfl, description="Dual constraint for RFL")
|
| 762 |
+
rfl_dual_constraint[j_rfl] = Sum(i_rfl, lambda_rfl[i_rfl] * S_rfl[j_rfl, i_rfl]) + \
|
| 763 |
+
muUB_rfl[j_rfl] - muLB_rfl[j_rfl] == 0
|
| 764 |
+
|
| 765 |
+
def FixSBMLs():
|
| 766 |
+
print("Fixing SBML files...")
|
| 767 |
+
|
| 768 |
+
def add_reaction(file_name, metabolite_code, metabolite_name, charge=0):
|
| 769 |
+
# Define the SBML document and model
|
| 770 |
+
reader = libsbml.SBMLReader()
|
| 771 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 772 |
+
model = document.getModel()
|
| 773 |
+
|
| 774 |
+
# Check if the cytosol species already exists
|
| 775 |
+
species_id = f'M_{metabolite_code}_c0'
|
| 776 |
+
if model.getSpecies(species_id) is None:
|
| 777 |
+
species = model.createSpecies()
|
| 778 |
+
species.setId(species_id)
|
| 779 |
+
species.setCompartment('c0')
|
| 780 |
+
species.setName(f'{metabolite_name}[c0]')
|
| 781 |
+
species.setCharge(charge)
|
| 782 |
+
species.setBoundaryCondition(False)
|
| 783 |
+
|
| 784 |
+
cytosol_species = model.getSpecies(species_id)
|
| 785 |
+
|
| 786 |
+
# create the extracellular species
|
| 787 |
+
species = model.createSpecies()
|
| 788 |
+
species.setId(f'M_{metabolite_code}_e0')
|
| 789 |
+
species.setCompartment('e0')
|
| 790 |
+
species.setName(f'{metabolite_name}[e0]')
|
| 791 |
+
species.setCharge(int(cytosol_species.getCharge()))
|
| 792 |
+
species.setBoundaryCondition(False)
|
| 793 |
+
|
| 794 |
+
|
| 795 |
+
# Create the export/import reaction
|
| 796 |
+
reaction = model.createReaction()
|
| 797 |
+
reaction.setId(f'EX_{metabolite_code}_e0')
|
| 798 |
+
reaction.setName(f'{metabolite_name} export/import')
|
| 799 |
+
reaction.setReversible(True) # Set reversibility
|
| 800 |
+
|
| 801 |
+
# Add reactant to the reaction
|
| 802 |
+
reactant1 = reaction.createReactant()
|
| 803 |
+
reactant1.setSpecies(f'M_{metabolite_code}_e0') # Use the species ID created above
|
| 804 |
+
reactant1.setStoichiometry(1)
|
| 805 |
+
reactant1.setConstant(False)
|
| 806 |
+
|
| 807 |
+
# 6. Define the kinetic law (e.g., Mass Action kinetics: k * S1)
|
| 808 |
+
kinetic_law = reaction.createKineticLaw()
|
| 809 |
+
# Create a parameter for the rate constant
|
| 810 |
+
lb = kinetic_law.createParameter()
|
| 811 |
+
lb.setId('LOWER_BOUND')
|
| 812 |
+
lb.setValue(-1000)
|
| 813 |
+
lb.setName('mmol_per_gDW_per_hr')
|
| 814 |
+
ub = kinetic_law.createParameter()
|
| 815 |
+
ub.setId('UPPER_BOUND')
|
| 816 |
+
ub.setValue(1000)
|
| 817 |
+
ub.setName('mmol_per_gDW_per_hr')
|
| 818 |
+
obj = kinetic_law.createParameter()
|
| 819 |
+
obj.setId('OBJECTIVE_COEFFICIENT')
|
| 820 |
+
obj.setValue(0)
|
| 821 |
+
flx = kinetic_law.createParameter()
|
| 822 |
+
flx.setId('FLUX_VALUE')
|
| 823 |
+
flx.setValue(0)
|
| 824 |
+
flx.setName('mmol_per_gDW_per_hr')
|
| 825 |
+
|
| 826 |
+
|
| 827 |
+
# Set the math for the kinetic law using MathML
|
| 828 |
+
# You can use libsbml.parseL3Formula to convert from infix string to MathML AST
|
| 829 |
+
math_ml_string = (
|
| 830 |
+
'<math xmlns="http://www.w3.org/1998/Math/MathML">'
|
| 831 |
+
'<ci> FLUX_VALUE </ci>'
|
| 832 |
+
'</math>'
|
| 833 |
+
)
|
| 834 |
+
math_ast = libsbml.readMathMLFromString(math_ml_string)
|
| 835 |
+
if math_ast:
|
| 836 |
+
kinetic_law.setMath(math_ast)
|
| 837 |
+
else:
|
| 838 |
+
print("Error: Could not parse MathML string.")
|
| 839 |
+
|
| 840 |
+
# create the reaction to convert from extracellular to cytosol
|
| 841 |
+
transport_reaction = model.createReaction()
|
| 842 |
+
transport_reaction.setId(f'R_{metabolite_code}_transport')
|
| 843 |
+
transport_reaction.setName(f'{metabolite_name} transport')
|
| 844 |
+
transport_reaction.setReversible(True) # Set reversibility
|
| 845 |
+
|
| 846 |
+
# Add reactant to the reaction
|
| 847 |
+
cytosol = transport_reaction.createReactant()
|
| 848 |
+
cytosol.setSpecies(f'M_{metabolite_code}_c0') # Use the species ID created above
|
| 849 |
+
cytosol.setStoichiometry(1)
|
| 850 |
+
cytosol.setConstant(False)
|
| 851 |
+
|
| 852 |
+
# Add product to the reaction
|
| 853 |
+
extracellular = transport_reaction.createProduct()
|
| 854 |
+
extracellular.setSpecies(f'M_{metabolite_code}_e0') # Use the species ID created above
|
| 855 |
+
extracellular.setStoichiometry(1)
|
| 856 |
+
extracellular.setConstant(False)
|
| 857 |
+
|
| 858 |
+
# 6. Define the kinetic law (e.g., Mass Action kinetics: k * S1)
|
| 859 |
+
kinetic_law = transport_reaction.createKineticLaw()
|
| 860 |
+
# Create a parameter for the rate constant
|
| 861 |
+
lb = kinetic_law.createParameter()
|
| 862 |
+
lb.setId('LOWER_BOUND')
|
| 863 |
+
lb.setValue(-1000)
|
| 864 |
+
lb.setName('mmol_per_gDW_per_hr')
|
| 865 |
+
ub = kinetic_law.createParameter()
|
| 866 |
+
ub.setId('UPPER_BOUND')
|
| 867 |
+
ub.setValue(1000)
|
| 868 |
+
ub.setName('mmol_per_gDW_per_hr')
|
| 869 |
+
obj = kinetic_law.createParameter()
|
| 870 |
+
obj.setId('OBJECTIVE_COEFFICIENT')
|
| 871 |
+
obj.setValue(0)
|
| 872 |
+
flx = kinetic_law.createParameter()
|
| 873 |
+
flx.setId('FLUX_VALUE')
|
| 874 |
+
flx.setValue(0)
|
| 875 |
+
flx.setName('mmol_per_gDW_per_hr')
|
| 876 |
+
|
| 877 |
+
|
| 878 |
+
# Set the math for the kinetic law using MathML
|
| 879 |
+
# You can use libsbml.parseL3Formula to convert from infix string to MathML AST
|
| 880 |
+
math_ml_string = (
|
| 881 |
+
'<math xmlns="http://www.w3.org/1998/Math/MathML">'
|
| 882 |
+
'<ci> FLUX_VALUE </ci>'
|
| 883 |
+
'</math>'
|
| 884 |
+
)
|
| 885 |
+
math_ast = libsbml.readMathMLFromString(math_ml_string)
|
| 886 |
+
if math_ast:
|
| 887 |
+
kinetic_law.setMath(math_ast)
|
| 888 |
+
else:
|
| 889 |
+
print("Error: Could not parse MathML string.")
|
| 890 |
+
|
| 891 |
+
libsbml.writeSBMLToFile(document, f'model files/{file_name}')
|
| 892 |
+
|
| 893 |
+
|
| 894 |
+
def add_version(file_name, version):
|
| 895 |
+
# Define the SBML document and model
|
| 896 |
+
reader = libsbml.SBMLReader()
|
| 897 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 898 |
+
model = document.getModel()
|
| 899 |
+
|
| 900 |
+
# Set the version in the model's annotation
|
| 901 |
+
model.setNotes(version)
|
| 902 |
+
|
| 903 |
+
# Write the updated SBML document back to file
|
| 904 |
+
libsbml.writeSBMLToFile(document, f'model files/{file_name}')
|
| 905 |
+
|
| 906 |
+
def check_version(file_name, version):
|
| 907 |
+
# Define the SBML document and model
|
| 908 |
+
reader = libsbml.SBMLReader()
|
| 909 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 910 |
+
model = document.getModel()
|
| 911 |
+
|
| 912 |
+
# Check if the version matches
|
| 913 |
+
notes = model.getNotesString()
|
| 914 |
+
return notes == f'<notes>{version}</notes>'
|
| 915 |
+
|
| 916 |
+
version = 'v2.5'
|
| 917 |
+
|
| 918 |
+
if check_version('M. gottschalkii.xml', version) is False:
|
| 919 |
+
print('M. gottschalkii.xml is not up to date, updating...')
|
| 920 |
+
add_reaction('M. gottschalkii.xml', 'cpd00035', 'L-Alanine')
|
| 921 |
+
add_reaction('M. gottschalkii.xml', 'cpd00107', 'L-Leucine')
|
| 922 |
+
add_reaction('M. gottschalkii.xml', 'cpd00033', 'Glycine')
|
| 923 |
+
add_version('M. gottschalkii.xml', version)
|
| 924 |
+
|
| 925 |
+
if check_version('P. ruminicola.xml', version) is False:
|
| 926 |
+
print('P. ruminicola.xml is not up to date, updating...')
|
| 927 |
+
add_reaction('P. ruminicola.xml', 'cpd00035', 'L-Alanine')
|
| 928 |
+
add_reaction('P. ruminicola.xml', 'cpd00107', 'L-Leucine')
|
| 929 |
+
add_reaction('P. ruminicola.xml', 'cpd00033', 'Glycine')
|
| 930 |
+
add_reaction('P. ruminicola.xml', 'cpd11657', 'Starch')
|
| 931 |
+
add_reaction('P. ruminicola.xml', 'cpd00076', 'Sucrose')
|
| 932 |
+
add_reaction('P. ruminicola.xml', 'cpd00053', 'L-Glutamine')
|
| 933 |
+
add_reaction('P. ruminicola.xml', 'cpd00161', 'L-Threonine')
|
| 934 |
+
add_reaction('P. ruminicola.xml', 'cpd00348', 'D-Galactose 1-phosphate')
|
| 935 |
+
add_reaction('P. ruminicola.xml', 'cpd00084', 'L-Cysteine')
|
| 936 |
+
add_reaction('P. ruminicola.xml', 'cpd00052', 'CTP')
|
| 937 |
+
add_reaction('P. ruminicola.xml', 'cpd00002', 'ATP')
|
| 938 |
+
add_reaction('P. ruminicola.xml', 'cpd00062', 'UTP')
|
| 939 |
+
add_reaction('P. ruminicola.xml', 'cpd00356', 'dCTP')
|
| 940 |
+
add_reaction('P. ruminicola.xml', 'cpd00073', 'Urea')
|
| 941 |
+
add_version('P. ruminicola.xml', version)
|
| 942 |
+
|
| 943 |
+
if check_version('R. flavefaciens.xml', version) is False:
|
| 944 |
+
print('R. flavefaciens.xml is not up to date, updating...')
|
| 945 |
+
add_reaction('R. flavefaciens.xml', 'cpd00035', 'L-Alanine')
|
| 946 |
+
add_reaction('R. flavefaciens.xml', 'cpd00033', 'Glycine')
|
| 947 |
+
add_reaction('R. flavefaciens.xml', 'cpd00053', 'L-Glutamine')
|
| 948 |
+
add_reaction('R. flavefaciens.xml', 'cpd00161', 'L-Threonine')
|
| 949 |
+
add_reaction('R. flavefaciens.xml', 'cpd00348', 'D-Galactose 1-phosphate')
|
| 950 |
+
add_reaction('R. flavefaciens.xml', 'cpd00084', 'L-Cysteine')
|
| 951 |
+
add_reaction('R. flavefaciens.xml', 'cpd00052', 'CTP')
|
| 952 |
+
add_reaction('R. flavefaciens.xml', 'cpd00002', 'ATP')
|
| 953 |
+
add_reaction('R. flavefaciens.xml', 'cpd00062', 'UTP')
|
| 954 |
+
add_reaction('R. flavefaciens.xml', 'cpd00356', 'dCTP')
|
| 955 |
+
add_reaction('R. flavefaciens.xml', 'cpd00073', 'Urea')
|
| 956 |
+
add_version('R. flavefaciens.xml', version)
|
| 957 |
+
|
| 958 |
+
|
| 959 |
+
def remove_duplicate_species_and_reactions(file_name):
|
| 960 |
+
# Define the SBML document and model
|
| 961 |
+
reader = libsbml.SBMLReader()
|
| 962 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 963 |
+
model = document.getModel()
|
| 964 |
+
|
| 965 |
+
# --- Remove Duplicate Species ---
|
| 966 |
+
seen_species = []
|
| 967 |
+
species_to_remove = []
|
| 968 |
+
|
| 969 |
+
for i in range(model.getNumSpecies()):
|
| 970 |
+
species = model.getSpecies(i)
|
| 971 |
+
id = species.getId()
|
| 972 |
+
|
| 973 |
+
if id in seen_species:
|
| 974 |
+
species_to_remove.append(species.getId())
|
| 975 |
+
else:
|
| 976 |
+
seen_species.append(species.getId())
|
| 977 |
+
|
| 978 |
+
# Remove species (iterate in reverse to avoid index issues)
|
| 979 |
+
for item in reversed(species_to_remove):
|
| 980 |
+
model.removeSpecies(item)
|
| 981 |
+
|
| 982 |
+
# --- Remove Duplicate Reactions ---
|
| 983 |
+
seen_reactions = []
|
| 984 |
+
reactions_to_remove = []
|
| 985 |
+
|
| 986 |
+
for i in range(model.getNumReactions()):
|
| 987 |
+
reaction = model.getReaction(i)
|
| 988 |
+
id = reaction.getId()
|
| 989 |
+
|
| 990 |
+
if id in seen_reactions:
|
| 991 |
+
reactions_to_remove.append(reaction.getId())
|
| 992 |
+
else:
|
| 993 |
+
seen_reactions.append(reaction.getId())
|
| 994 |
+
|
| 995 |
+
# Remove reactions
|
| 996 |
+
for reaction_id in reversed(reactions_to_remove):
|
| 997 |
+
model.removeReaction(reaction_id)
|
| 998 |
+
|
| 999 |
+
# Save the modified model (optional)
|
| 1000 |
+
writer = libsbml.SBMLWriter()
|
| 1001 |
+
libsbml.writeSBMLToFile(document, f'model files/{file_name}')
|
| 1002 |
+
|
| 1003 |
+
remove_duplicate_species_and_reactions('M. gottschalkii.xml')
|
| 1004 |
+
remove_duplicate_species_and_reactions('P. ruminicola.xml')
|
| 1005 |
+
remove_duplicate_species_and_reactions('R. flavefaciens.xml')
|
| 1006 |
+
|
| 1007 |
+
# removing a duplicate product that slipped through the cracks
|
| 1008 |
+
|
| 1009 |
+
reader = libsbml.SBMLReader()
|
| 1010 |
+
document = reader.readSBML(f'model files/R. flavefaciens.xml')
|
| 1011 |
+
model = document.getModel()
|
| 1012 |
+
|
| 1013 |
+
reaction = model.getReaction('R_R01896_c0')
|
| 1014 |
+
reaction.removeProduct('M_cpd00067_c0')
|
| 1015 |
+
|
| 1016 |
+
writer = libsbml.SBMLWriter()
|
| 1017 |
+
libsbml.writeSBMLToFile(document, f'model files/R. flavefaciens.xml')
|
| 1018 |
+
|
| 1019 |
+
def solve(solver_name='IPOPT'):
|
| 1020 |
+
|
| 1021 |
+
|
| 1022 |
+
global model
|
| 1023 |
+
# Create model
|
| 1024 |
+
model = Model(container=cowmunity, name="COWMUNITY", equations=cowmunity.getEquations(),
|
| 1025 |
+
problem="NLP", sense=Sense.MAX, objective=objective_variable)
|
| 1026 |
+
|
| 1027 |
+
# Set solver options
|
| 1028 |
+
options = Options(nlp=solver_name, equation_listing_limit=10, variable_listing_limit=10, time_limit=20, threads=0)
|
| 1029 |
+
|
| 1030 |
+
# Solve the model
|
| 1031 |
+
print(f"Solving with {solver_name}...")
|
| 1032 |
+
model.solve(options=options)
|
| 1033 |
+
|
| 1034 |
+
# check solution status
|
| 1035 |
+
status = model.solve_status
|
| 1036 |
+
if status == SolveStatus.NormalCompletion:
|
| 1037 |
+
print("Optimal solution found!")
|
| 1038 |
+
else:
|
| 1039 |
+
print(f"Solver terminated with status: {status}")
|
| 1040 |
+
|
| 1041 |
+
def extract_results():
|
| 1042 |
+
"""Extract and store results"""
|
| 1043 |
+
global results
|
| 1044 |
+
results = {
|
| 1045 |
+
'objective_value': objective_variable.records['level'].iloc[0],
|
| 1046 |
+
'mgk_biomass': v_mgk.records.loc[v_mgk.records['j_mgk'] == 'R_biomass0', 'level'].iloc[0],
|
| 1047 |
+
'prm_biomass': v_prm.records.loc[v_prm.records['j_prm'] == 'R_biomass0', 'level'].iloc[0],
|
| 1048 |
+
'rfl_biomass': v_rfl.records.loc[v_rfl.records['j_rfl'] == 'R_biomass0', 'level'].iloc[0],
|
| 1049 |
+
'methane_flux' : v_mgk.records.loc[v_mgk.records['j_mgk'] == 'EX_cpd01024_e0', 'level'].iloc[0]
|
| 1050 |
+
}
|
| 1051 |
+
|
| 1052 |
+
def save_results(treatment, methane = 'variable'):
|
| 1053 |
+
"""Save results to a CSV file"""
|
| 1054 |
+
os.makedirs(f'results/{methane}_methane_{treatment}_treatment', exist_ok=True)
|
| 1055 |
+
v_mgk.records.to_csv(f'results/{methane}_methane_{treatment}_treatment/mgk_records.csv', index=False)
|
| 1056 |
+
v_prm.records.to_csv(f'results/{methane}_methane_{treatment}_treatment/prm_records.csv', index=False)
|
| 1057 |
+
v_rfl.records.to_csv(f'results/{methane}_methane_{treatment}_treatment/rfl_records.csv', index=False)
|
| 1058 |
+
print(f"Results saved to 'results/{methane}_methane_{treatment}_treatment'.")
|
| 1059 |
+
|
| 1060 |
+
def print_results():
|
| 1061 |
+
"""Print results in a formatted way"""
|
| 1062 |
+
print()
|
| 1063 |
+
print("********************* RESULTS *********************")
|
| 1064 |
+
print(f"Total Biomass = {results['objective_value']:5f}")
|
| 1065 |
+
print()
|
| 1066 |
+
|
| 1067 |
+
print("********************* MGK *************************")
|
| 1068 |
+
print(f"MGK Biomass Flux = {results['mgk_biomass']:5f}")
|
| 1069 |
+
print(f"Methane Emission Flux = {results['methane_flux']:5f}")
|
| 1070 |
+
print()
|
| 1071 |
+
|
| 1072 |
+
print("********************* PRM *************************")
|
| 1073 |
+
print(f"PRM Biomass Flux = {results['prm_biomass']:5f}")
|
| 1074 |
+
print()
|
| 1075 |
+
|
| 1076 |
+
print("********************* RFL *************************")
|
| 1077 |
+
print(f"RFL Biomass Flux = {results['rfl_biomass']:5f}")
|
| 1078 |
+
print()
|
| 1079 |
+
|
| 1080 |
+
def bug_huntin():
|
| 1081 |
+
# This function is for debugging purposes, to check the model and variable records
|
| 1082 |
+
|
| 1083 |
+
def print_reaction(reaction):
|
| 1084 |
+
def check_reaction(reaction, file_name):
|
| 1085 |
+
reader = libsbml.SBMLReader()
|
| 1086 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1087 |
+
model = document.getModel()
|
| 1088 |
+
|
| 1089 |
+
reaction = model.getReaction(reaction)
|
| 1090 |
+
|
| 1091 |
+
if reaction is None:
|
| 1092 |
+
return None
|
| 1093 |
+
else:
|
| 1094 |
+
return reaction.getId()
|
| 1095 |
+
|
| 1096 |
+
if check_reaction(reaction, 'M. gottschalkii.xml') is None:
|
| 1097 |
+
print(f'Reaction {reaction} not found in M. gottschalkii model.')
|
| 1098 |
+
else:
|
| 1099 |
+
mgk_flux = v_mgk.records.loc[v_mgk.records['j_mgk'] == reaction.strip(), 'level'].iloc[0]
|
| 1100 |
+
print(f'MGK {reaction}: {mgk_flux}')
|
| 1101 |
+
if check_reaction(reaction, 'P. ruminicola.xml') is None:
|
| 1102 |
+
print(f'Reaction {reaction} not found in P. ruminicola model.')
|
| 1103 |
+
else:
|
| 1104 |
+
prm_flux = v_prm.records.loc[v_prm.records['j_prm'] == reaction.strip(), 'level'].iloc[0]
|
| 1105 |
+
print(f'PRM {reaction}: {prm_flux}')
|
| 1106 |
+
if check_reaction(reaction, 'R. flavefaciens.xml') is None:
|
| 1107 |
+
print(f'Reaction {reaction} not found in R. flavefaciens model.')
|
| 1108 |
+
else:
|
| 1109 |
+
rfl_flux = v_rfl.records.loc[v_rfl.records['j_rfl'] == reaction.strip(), 'level'].iloc[0]
|
| 1110 |
+
print(f'RFL {reaction}: {rfl_flux}')
|
| 1111 |
+
|
| 1112 |
+
|
| 1113 |
+
print_reaction('EX_cpd01188_e0')
|
| 1114 |
+
|
| 1115 |
+
|
| 1116 |
+
|
| 1117 |
+
def flux_investigation(file_name, v_set, j_set, i_set, metabolite):
|
| 1118 |
+
|
| 1119 |
+
reader = libsbml.SBMLReader()
|
| 1120 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1121 |
+
model = document.getModel()
|
| 1122 |
+
|
| 1123 |
+
relevant_reactions = []
|
| 1124 |
+
for i in range(model.getNumReactions()):
|
| 1125 |
+
reaction = model.getReaction(i)
|
| 1126 |
+
product = reaction.getProduct(metabolite)
|
| 1127 |
+
if product is None:
|
| 1128 |
+
continue
|
| 1129 |
+
else:
|
| 1130 |
+
relevant_reactions.append(reaction.id)
|
| 1131 |
+
|
| 1132 |
+
# species = model.getSpecies(metabolite)
|
| 1133 |
+
name = i_set.records.loc[i_set.records['index'] == metabolite, 'element_text'].iloc[0]
|
| 1134 |
+
print(file_name)
|
| 1135 |
+
print(f'\n*** {name} FLUXES ***')
|
| 1136 |
+
for item in relevant_reactions:
|
| 1137 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1138 |
+
print(f'{item} : {flux}')
|
| 1139 |
+
|
| 1140 |
+
print()
|
| 1141 |
+
|
| 1142 |
+
metabolite = 'M_cpd00033_c0'
|
| 1143 |
+
mgk = ('M. gottschalkii.xml', v_mgk, 'j_mgk', i_mgk)
|
| 1144 |
+
prm = ('P. ruminicola.xml', v_prm, 'j_prm', i_prm)
|
| 1145 |
+
rfl = ('R. flavefaciens.xml', v_rfl, 'j_rfl', i_rfl)
|
| 1146 |
+
|
| 1147 |
+
# flux_investigation(*mgk, metabolite)
|
| 1148 |
+
|
| 1149 |
+
def biomass_fluxes(file_name, v_set, j_set, i_set):
|
| 1150 |
+
list_to_investigate = []
|
| 1151 |
+
print()
|
| 1152 |
+
print('*'*10, file_name, '*'*10)
|
| 1153 |
+
|
| 1154 |
+
reader = libsbml.SBMLReader()
|
| 1155 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1156 |
+
model = document.getModel()
|
| 1157 |
+
|
| 1158 |
+
biomass_reactants = []
|
| 1159 |
+
biomass_reaction = model.getReaction('R_biomass0')
|
| 1160 |
+
for i in range(biomass_reaction.getNumReactants()):
|
| 1161 |
+
reactant = biomass_reaction.getReactant(i)
|
| 1162 |
+
biomass_reactants.append(reactant.getSpecies())
|
| 1163 |
+
|
| 1164 |
+
precursor_reactions = {}
|
| 1165 |
+
for item in biomass_reactants:
|
| 1166 |
+
relevant_reactions = []
|
| 1167 |
+
for i in range(model.getNumReactions()):
|
| 1168 |
+
reaction = model.getReaction(i)
|
| 1169 |
+
product = reaction.getProduct(f'{item}')
|
| 1170 |
+
if product is None:
|
| 1171 |
+
continue
|
| 1172 |
+
else:
|
| 1173 |
+
relevant_reactions.append(reaction.id)
|
| 1174 |
+
new_entry = {item : relevant_reactions}
|
| 1175 |
+
precursor_reactions.update(new_entry)
|
| 1176 |
+
|
| 1177 |
+
for key in precursor_reactions:
|
| 1178 |
+
flux_set = []
|
| 1179 |
+
relevant_reactions = precursor_reactions[key]
|
| 1180 |
+
species = biomass_reaction.getReactant(f'{key}').getSpecies()
|
| 1181 |
+
name = i_set.records.loc[i_set.records['index'] == species, 'element_text'].iloc[0]
|
| 1182 |
+
print(f'\n{name} FLUXES')
|
| 1183 |
+
for item in relevant_reactions:
|
| 1184 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1185 |
+
print(f'{item} : {flux}')
|
| 1186 |
+
flux_set.append(flux)
|
| 1187 |
+
print(f'Total flux for {name} = {sum(flux_set)}')
|
| 1188 |
+
if sum(flux_set) <= 1e-5:
|
| 1189 |
+
list_to_investigate.append(name)
|
| 1190 |
+
|
| 1191 |
+
print(f'\nBiomass precursors with zero or negative production:')
|
| 1192 |
+
for item in list_to_investigate:
|
| 1193 |
+
print(item)
|
| 1194 |
+
|
| 1195 |
+
print(model.getNumReactions(), 'reactions in the model')
|
| 1196 |
+
print(model.getNumSpecies(), 'species in the model')
|
| 1197 |
+
|
| 1198 |
+
# biomass_fluxes(*mgk)
|
| 1199 |
+
# biomass_fluxes(*prm)
|
| 1200 |
+
# biomass_fluxes(*rfl)
|
| 1201 |
+
|
| 1202 |
+
def zero_flux_reactions(file_name, v_set, j_set, i_set):
|
| 1203 |
+
reader = libsbml.SBMLReader()
|
| 1204 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1205 |
+
model = document.getModel()
|
| 1206 |
+
|
| 1207 |
+
"""Return a list of reaction IDs in v_set where the flux is exactly zero."""
|
| 1208 |
+
zero_flux_df = v_set.records.loc[v_set.records['level'] == 0]
|
| 1209 |
+
zero_flux_list = zero_flux_df[j_set].tolist()
|
| 1210 |
+
|
| 1211 |
+
print(f'\n*** {file_name} REACTIONS WITH ZERO FLUX ***')
|
| 1212 |
+
for item in zero_flux_list:
|
| 1213 |
+
precursor_reactions = {}
|
| 1214 |
+
needy_dict = {}
|
| 1215 |
+
unmade_products = []
|
| 1216 |
+
zero_reaction = model.getReaction(item)
|
| 1217 |
+
for i in range(zero_reaction.getNumProducts()):
|
| 1218 |
+
product = zero_reaction.getProduct(i)
|
| 1219 |
+
unmade_products.append(product.getSpecies())
|
| 1220 |
+
print(f'\n{item}')
|
| 1221 |
+
for item in unmade_products:
|
| 1222 |
+
relevant_reactions = []
|
| 1223 |
+
needy_reactions = []
|
| 1224 |
+
for i in range(model.getNumReactions()):
|
| 1225 |
+
reaction = model.getReaction(i)
|
| 1226 |
+
product = reaction.getProduct(f'{item}')
|
| 1227 |
+
if product is None:
|
| 1228 |
+
continue
|
| 1229 |
+
else:
|
| 1230 |
+
relevant_reactions.append(reaction.id)
|
| 1231 |
+
new_entry = {item : relevant_reactions}
|
| 1232 |
+
precursor_reactions.update(new_entry)
|
| 1233 |
+
|
| 1234 |
+
for i in range(model.getNumReactions()):
|
| 1235 |
+
reaction = model.getReaction(i)
|
| 1236 |
+
reactant = reaction.getReactant(f'{item}')
|
| 1237 |
+
if reactant is None:
|
| 1238 |
+
continue
|
| 1239 |
+
else:
|
| 1240 |
+
needy_reactions.append(reaction.id)
|
| 1241 |
+
new_entry = {item : relevant_reactions}
|
| 1242 |
+
precursor_reactions.update(new_entry)
|
| 1243 |
+
new_entry = {item : needy_reactions}
|
| 1244 |
+
needy_dict.update(new_entry)
|
| 1245 |
+
|
| 1246 |
+
for key in precursor_reactions:
|
| 1247 |
+
relevant_reactions = precursor_reactions[key]
|
| 1248 |
+
product = zero_reaction.getProduct(f'{key}')
|
| 1249 |
+
species = product.getSpecies()
|
| 1250 |
+
name = i_set.records.loc[i_set.records['index'] == species, 'element_text'].iloc[0]
|
| 1251 |
+
print(f'Reactions that produce {name} ({species}):')
|
| 1252 |
+
for item in relevant_reactions:
|
| 1253 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1254 |
+
print(f'{item} : {flux}')
|
| 1255 |
+
print(f'Reactions that require {name} ({species}):')
|
| 1256 |
+
for item in needy_reactions:
|
| 1257 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1258 |
+
print(f'{item} : {flux}')
|
| 1259 |
+
|
| 1260 |
+
|
| 1261 |
+
|
| 1262 |
+
# zero_flux_reactions(*mgk)
|
| 1263 |
+
# zero_flux_reactions(*prm)
|
| 1264 |
+
# zero_flux_reactions(*rfl)
|
| 1265 |
+
|
| 1266 |
+
|
| 1267 |
+
|
| 1268 |
+
|
| 1269 |
+
|
| 1270 |
+
|
| 1271 |
+
|
Cowmunity.py
ADDED
|
@@ -0,0 +1,1307 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pandas as pd
|
| 2 |
+
import libsbml
|
| 3 |
+
from gamspy import Container, Set, Parameter, Variable, Equation, Model, Sum, Sense, Options, SpecialValues, SolveStatus
|
| 4 |
+
import os
|
| 5 |
+
|
| 6 |
+
def Sets():
|
| 7 |
+
print("Creating sets...")
|
| 8 |
+
global cowmunity
|
| 9 |
+
|
| 10 |
+
cowmunity = Container()
|
| 11 |
+
|
| 12 |
+
global j_mgk, j_prm, j_rfl, i_mgk, i_prm, i_rfl
|
| 13 |
+
|
| 14 |
+
j_mgk = Set(container=cowmunity, name="j_mgk", description="M. Gottschalkii reactions")
|
| 15 |
+
j_prm = Set(container=cowmunity, name="j_prm", description="P. ruminicola reactions")
|
| 16 |
+
j_rfl = Set(container=cowmunity, name="j_rfl", description="R. flavefaciens reactions")
|
| 17 |
+
|
| 18 |
+
i_mgk = Set(container=cowmunity, name="i_mgk", description="M. Gottschalkii metabolites")
|
| 19 |
+
i_prm = Set(container=cowmunity, name="i_prm", description="P. ruminicola metabolites")
|
| 20 |
+
i_rfl = Set(container=cowmunity, name="i_rfl", description="R. flavefaciens metabolites")
|
| 21 |
+
|
| 22 |
+
def extract_metabolites(xml_file_path, GAMSpy_set):
|
| 23 |
+
# Parse the XML file
|
| 24 |
+
reader = libsbml.SBMLReader()
|
| 25 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 26 |
+
model = document.getModel()
|
| 27 |
+
if model is None:
|
| 28 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 29 |
+
|
| 30 |
+
# Extract names and store them in a list
|
| 31 |
+
met_name = {}
|
| 32 |
+
for i in range(model.getNumSpecies()):
|
| 33 |
+
species = model.getSpecies(i)
|
| 34 |
+
new_entry = {species.id : species.getName()[0:63]}
|
| 35 |
+
met_name.update(new_entry)
|
| 36 |
+
df = pd.DataFrame.from_dict(met_name, orient='index', columns=['name'])
|
| 37 |
+
|
| 38 |
+
# add the names to the GAMSpy Set
|
| 39 |
+
GAMSpy_set.setRecords(df.reset_index())
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def extract_reactions(xml_file_path, GAMSpy_set):
|
| 43 |
+
# Parse the XML file
|
| 44 |
+
reader = libsbml.SBMLReader()
|
| 45 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 46 |
+
model = document.getModel()
|
| 47 |
+
if model is None:
|
| 48 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 49 |
+
|
| 50 |
+
# Extract names and store them in a list
|
| 51 |
+
rxn_name = {}
|
| 52 |
+
for i in range(model.getNumReactions()):
|
| 53 |
+
reaction = model.getReaction(i)
|
| 54 |
+
new_entry = {reaction.id : reaction.getName()[0:63]}
|
| 55 |
+
rxn_name.update(new_entry)
|
| 56 |
+
df = pd.DataFrame.from_dict(rxn_name, orient='index', columns=['name'])
|
| 57 |
+
|
| 58 |
+
# add the names to the GAMSpy Set
|
| 59 |
+
GAMSpy_set.setRecords(df.reset_index())
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
extract_reactions('M. gottschalkii.xml', j_mgk)
|
| 63 |
+
extract_reactions('P. ruminicola.xml', j_prm)
|
| 64 |
+
extract_reactions('R. flavefaciens.xml', j_rfl)
|
| 65 |
+
|
| 66 |
+
extract_metabolites('M. gottschalkii.xml', i_mgk)
|
| 67 |
+
extract_metabolites('P. ruminicola.xml', i_prm)
|
| 68 |
+
extract_metabolites('R. flavefaciens.xml', i_rfl)
|
| 69 |
+
|
| 70 |
+
def Parameters():
|
| 71 |
+
print("Adding model parameters...")
|
| 72 |
+
global ub_mgk, ub_prm, ub_rfl, lb_mgk, lb_prm, lb_rfl
|
| 73 |
+
|
| 74 |
+
ub_mgk = Parameter(container=cowmunity, name="ub_mgk", domain=j_mgk, description="Upper bound for M. Gottschalkii reactions")
|
| 75 |
+
lb_mgk = Parameter(container=cowmunity, name="lb_mgk", domain=j_mgk, description="Lower bound for M. Gottschalkii reactions")
|
| 76 |
+
|
| 77 |
+
ub_prm = Parameter(container=cowmunity, name="ub_prm", domain=j_prm, description="Upper bound for P. ruminicola reactions")
|
| 78 |
+
lb_prm = Parameter(container=cowmunity, name="lb_prm", domain=j_prm, description="Lower bound for P. ruminicola reactions")
|
| 79 |
+
|
| 80 |
+
ub_rfl = Parameter(container=cowmunity, name="ub_rfl", domain=j_rfl, description="Upper bound for R. flavefaciens reactions")
|
| 81 |
+
lb_rfl = Parameter(container=cowmunity, name="lb_rfl", domain=j_rfl, description="Lower bound for R. flavefaciens reactions")
|
| 82 |
+
|
| 83 |
+
# define the reaction types for each reaction, whether they are reversible (1) or irreversible (0)
|
| 84 |
+
|
| 85 |
+
rxntype_mgk = Parameter(container=cowmunity, name="rxntype_mgk", domain=j_mgk, description="Reaction type for M. Gottschalkii reactions")
|
| 86 |
+
rxntype_prm = Parameter(container=cowmunity, name="rxntype_prm", domain=j_prm, description="Reaction type for P. ruminicola reactions")
|
| 87 |
+
rxntype_rfl = Parameter(container=cowmunity, name="rxntype_rfl", domain=j_rfl, description="Reaction type for R. flavefaciens reactions")
|
| 88 |
+
|
| 89 |
+
# define the stoichiometric matrix for each species, which describes the relationship between reactions and metabolites
|
| 90 |
+
# gives the coefficients for each reaction
|
| 91 |
+
|
| 92 |
+
global S_mgk, S_prm, S_rfl
|
| 93 |
+
|
| 94 |
+
S_mgk = Parameter(container=cowmunity, name="S_mgk", domain=[j_mgk, i_mgk], description="Stoichiometric matrix for M. Gottschalkii")
|
| 95 |
+
S_prm = Parameter(container=cowmunity, name="S_prm", domain=[j_prm, i_prm], description="Stoichiometric matrix for P. ruminicola")
|
| 96 |
+
S_rfl = Parameter(container=cowmunity, name="S_rfl", domain=[j_rfl, i_rfl], description="Stoichiometric matrix for R. flavefaciens")
|
| 97 |
+
|
| 98 |
+
# define whether each reaction is an exchange reaction
|
| 99 |
+
|
| 100 |
+
ex_mgk = Parameter(container=cowmunity, name="ex_mgk", domain=j_mgk, description="Exchange for M. Gottschalkii reactions")
|
| 101 |
+
ex_prm = Parameter(container=cowmunity, name="ex_prm", domain=j_prm, description="Exchange for P. ruminicola reactions")
|
| 102 |
+
ex_rfl = Parameter(container=cowmunity, name="ex_rfl", domain=j_rfl, description="Exchange for R. flavefaciens reactions")
|
| 103 |
+
|
| 104 |
+
def extract_rxn_type(xml_file_path, GAMSpy_parameter):
|
| 105 |
+
# Parse the XML file
|
| 106 |
+
reader = libsbml.SBMLReader()
|
| 107 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 108 |
+
model = document.getModel()
|
| 109 |
+
if model is None:
|
| 110 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 111 |
+
# Extract names and store them in a list
|
| 112 |
+
type_dict = {}
|
| 113 |
+
for i in range(model.getNumReactions()):
|
| 114 |
+
reaction = model.getReaction(i)
|
| 115 |
+
rxn_type = reaction.getReversible()
|
| 116 |
+
if rxn_type:
|
| 117 |
+
rxn_type = 1
|
| 118 |
+
else:
|
| 119 |
+
rxn_type = 0
|
| 120 |
+
new_entry = {reaction.id : rxn_type}
|
| 121 |
+
type_dict.update(new_entry)
|
| 122 |
+
|
| 123 |
+
df = pd.DataFrame.from_dict(type_dict, orient='index', columns=['name'])
|
| 124 |
+
|
| 125 |
+
# add the names to the GAMSpy Set
|
| 126 |
+
GAMSpy_parameter.setRecords(df.reset_index())
|
| 127 |
+
|
| 128 |
+
|
| 129 |
+
def extract_matrix(xml_file_path, GAMSpy_parameter):
|
| 130 |
+
# Parse the XML file
|
| 131 |
+
reader = libsbml.SBMLReader()
|
| 132 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 133 |
+
model = document.getModel()
|
| 134 |
+
if model is None:
|
| 135 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 136 |
+
# Extract reactions, metabolites, and their stoichiometry
|
| 137 |
+
df = pd.DataFrame()
|
| 138 |
+
for i in range(model.getNumReactions()):
|
| 139 |
+
reaction = model.getReaction(i)
|
| 140 |
+
for i in range(reaction.getNumReactants()):
|
| 141 |
+
reactant = reaction.getReactant(i)
|
| 142 |
+
metabolite_id = reactant.species
|
| 143 |
+
stoich = reactant.stoichiometry
|
| 144 |
+
new_row_df = pd.DataFrame({'reaction': [reaction.id], 'metabolite': [metabolite_id], 'stoichiometry': [-stoich]})
|
| 145 |
+
df = pd.concat([df, new_row_df], ignore_index=True)
|
| 146 |
+
for i in range(reaction.getNumProducts()):
|
| 147 |
+
product = reaction.getProduct(i)
|
| 148 |
+
metabolite_id = product.species
|
| 149 |
+
stoich = product.stoichiometry
|
| 150 |
+
new_row_df = pd.DataFrame({'reaction': [reaction.id], 'metabolite': [metabolite_id], 'stoichiometry': [stoich]})
|
| 151 |
+
df = pd.concat([df, new_row_df], ignore_index=True)
|
| 152 |
+
|
| 153 |
+
df = df.set_index(['reaction', 'metabolite'])
|
| 154 |
+
|
| 155 |
+
|
| 156 |
+
# add the names to the GAMSpy Set
|
| 157 |
+
GAMSpy_parameter.setRecords(df.reset_index())
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
def extract_exchange_type(xml_file_path, GAMSpy_parameter):
|
| 161 |
+
# Parse the XML file
|
| 162 |
+
reader = libsbml.SBMLReader()
|
| 163 |
+
document = reader.readSBML(f'model files/{xml_file_path}')
|
| 164 |
+
model = document.getModel()
|
| 165 |
+
if model is None:
|
| 166 |
+
raise ValueError("The SBML model could not be parsed or is empty.")
|
| 167 |
+
# Extract names and store them in a list
|
| 168 |
+
type_dict = {}
|
| 169 |
+
ex_count = 0
|
| 170 |
+
for i in range(model.getNumReactions()):
|
| 171 |
+
reaction = model.getReaction(i)
|
| 172 |
+
if 'EX_' in reaction.id:
|
| 173 |
+
ex_type = 1
|
| 174 |
+
ex_count += 1
|
| 175 |
+
else:
|
| 176 |
+
ex_type = 0
|
| 177 |
+
new_entry = {reaction.id : ex_type}
|
| 178 |
+
type_dict.update(new_entry)
|
| 179 |
+
|
| 180 |
+
df = pd.DataFrame.from_dict(type_dict, orient='index', columns=['name'])
|
| 181 |
+
|
| 182 |
+
# add the names to the GAMSpy Set
|
| 183 |
+
GAMSpy_parameter.setRecords(df.reset_index())
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
extract_rxn_type('M. gottschalkii.xml', rxntype_mgk)
|
| 187 |
+
extract_rxn_type('P. ruminicola.xml', rxntype_prm)
|
| 188 |
+
extract_rxn_type('R. flavefaciens.xml', rxntype_rfl)
|
| 189 |
+
|
| 190 |
+
extract_matrix('M. gottschalkii.xml', S_mgk)
|
| 191 |
+
extract_matrix('P. ruminicola.xml', S_prm)
|
| 192 |
+
extract_matrix('R. flavefaciens.xml', S_rfl)
|
| 193 |
+
|
| 194 |
+
extract_exchange_type('M. gottschalkii.xml', ex_mgk)
|
| 195 |
+
extract_exchange_type('P. ruminicola.xml', ex_prm)
|
| 196 |
+
extract_exchange_type('R. flavefaciens.xml', ex_rfl)
|
| 197 |
+
|
| 198 |
+
# using a scalar parameter to define the maximum flux for each reaction, this is a constant that will be used in the model
|
| 199 |
+
|
| 200 |
+
Vmax = Parameter(container=cowmunity, name='Vmax', records=1000)
|
| 201 |
+
|
| 202 |
+
# set the reaction bounds for the irreversible reactions, reaction type 0
|
| 203 |
+
|
| 204 |
+
ub_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 0] = Vmax
|
| 205 |
+
lb_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 0] = SpecialValues.EPS # using SpecialValues.EPS to avoid zero lower bounds, which can cause issues in some solvers
|
| 206 |
+
|
| 207 |
+
ub_prm[j_prm].where[rxntype_prm[j_prm] == 0] = Vmax
|
| 208 |
+
lb_prm[j_prm].where[rxntype_prm[j_prm] == 0] = SpecialValues.EPS
|
| 209 |
+
|
| 210 |
+
ub_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 0] = Vmax
|
| 211 |
+
lb_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 0] = SpecialValues.EPS
|
| 212 |
+
|
| 213 |
+
# set the reaction bounds for the reversible reactions, reaction type 1
|
| 214 |
+
|
| 215 |
+
ub_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 1] = Vmax
|
| 216 |
+
lb_mgk[j_mgk].where[rxntype_mgk[j_mgk] == 1] = -Vmax
|
| 217 |
+
|
| 218 |
+
ub_prm[j_prm].where[rxntype_prm[j_prm] == 1] = Vmax
|
| 219 |
+
lb_prm[j_prm].where[rxntype_prm[j_prm] == 1] = -Vmax
|
| 220 |
+
|
| 221 |
+
ub_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 1] = Vmax
|
| 222 |
+
lb_rfl[j_rfl].where[rxntype_rfl[j_rfl] == 1] = -Vmax
|
| 223 |
+
|
| 224 |
+
def Variables(variable_choice, treatment='no', methane='variable'):
|
| 225 |
+
global v_mgk, v_prm, v_rfl, biomass_outer, ATP_outer, objective_variable
|
| 226 |
+
|
| 227 |
+
biomass_outer = Variable(container=cowmunity, name="biomass_outer", description="Outer problem Biomass objective function")
|
| 228 |
+
ATP_outer = Variable(container=cowmunity, name="ATP_outer", description="Outer problem ATP objective function")
|
| 229 |
+
|
| 230 |
+
if variable_choice == 'biomass_outer':
|
| 231 |
+
objective_variable = biomass_outer
|
| 232 |
+
if variable_choice == 'ATP_outer':
|
| 233 |
+
objective_variable = ATP_outer
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
v_mgk = Variable(container=cowmunity, name="v_mgk", domain=j_mgk, description="Fluxes for M. Gottschalkii reactions")
|
| 237 |
+
v_prm = Variable(container=cowmunity, name="v_prm", domain=j_prm, description="Fluxes for P. ruminicola reactions")
|
| 238 |
+
v_rfl = Variable(container=cowmunity, name="v_rfl", domain=j_rfl, description="Fluxes for R. flavefaciens reactions")
|
| 239 |
+
|
| 240 |
+
global lambda_mgk, lambda_prm, lambda_rfl
|
| 241 |
+
|
| 242 |
+
# Dual variables for the mass balance
|
| 243 |
+
lambda_mgk = Variable(container=cowmunity, name="lambda_mgk", domain=i_mgk, description="Dual variables for M. Gottschalkii metabolites")
|
| 244 |
+
lambda_prm = Variable(container=cowmunity, name="lambda_prm", domain=i_prm, description="Dual variables for P. ruminicola metabolites")
|
| 245 |
+
lambda_rfl = Variable(container=cowmunity, name="lambda_rfl", domain=i_rfl, description="Dual variables for R. flavefaciens metabolites")
|
| 246 |
+
|
| 247 |
+
# defining the flux bounds for each reaction as the upper and lower bounds defined above
|
| 248 |
+
v_mgk.lo[j_mgk] = lb_mgk[j_mgk]
|
| 249 |
+
v_mgk.up[j_mgk] = ub_mgk[j_mgk]
|
| 250 |
+
v_prm.lo[j_prm] = lb_prm[j_prm]
|
| 251 |
+
v_prm.up[j_prm] = ub_prm[j_prm]
|
| 252 |
+
v_rfl.lo[j_rfl] = lb_rfl[j_rfl]
|
| 253 |
+
v_rfl.up[j_rfl] = ub_rfl[j_rfl]
|
| 254 |
+
|
| 255 |
+
# ****** indicates the metabolite is transferred between species, so I will not set a flux for the species that does not take it up
|
| 256 |
+
# commented lines are those determined to have a greater capacity due to the potential for transfer between species
|
| 257 |
+
# the 4.55 indicates a conversion factor for dry whole weight to dry cell weight, as the model is based on dry cell weight
|
| 258 |
+
|
| 259 |
+
# v_prm.lo['EX_cpd11657_e0'] = -0.965423023 * 4.55 # uptake rate for Starch, fed to the model as two glucose units
|
| 260 |
+
v_prm.lo['EX_cpd00076_e0'] = -0.834726132 * 4.55 # uptake rate for Sucrose
|
| 261 |
+
v_rfl.lo['EX_cpd00076_e0'] = -0.834726132 * 4.55
|
| 262 |
+
v_prm.lo['EX_cpd00053_e0'] = -1.597816364 * 4.55 # uptake rate for L-Glutamine
|
| 263 |
+
v_rfl.lo['EX_cpd00053_e0'] = -1.597816364 * 4.55
|
| 264 |
+
# v_prm.lo['EX_cpd00027_e0'] = -0.794397609 * 4.55 # uptake rate for D-glucose *****
|
| 265 |
+
v_rfl.lo['EX_cpd00027_e0'] = (-0.794397609 + (-0.965423023 * 2)) * 4.55 # adjusted for the uptake of Starch
|
| 266 |
+
v_rfl.lo['EX_cpd00107_e0'] = -1.148366562 * 4.55 # uptake rate for L-Leucine
|
| 267 |
+
v_prm.lo['EX_cpd00107_e0'] = -1.148366562 * 4.55
|
| 268 |
+
# v_prm.lo['EX_cpd00224_e0'] = -0.666427627 * 4.55 # uptake rate for L-arabinose *****
|
| 269 |
+
v_rfl.lo['EX_cpd00224_e0'] = -0.666427627 * 4.55
|
| 270 |
+
# v_prm.lo['EX_cpd00035_e0'] = -0.938846598 * 4.55 # uptake rate for L-Alanine ****
|
| 271 |
+
# v_rfl.lo['EX_cpd00035_e0'] = -0.938846598 * 4.55
|
| 272 |
+
v_prm.lo['EX_cpd00132_e0'] = -0.400330802 * 4.55 # uptake rate for L-Asparagine
|
| 273 |
+
v_rfl.lo['EX_cpd00066_e0'] = -0.310015056 * 4.55 # uptake rate for L-Phenylalanine
|
| 274 |
+
v_rfl.lo['EX_cpd00156_e0'] = -0.385856944 * 4.55 # uptake rate for L-Valine
|
| 275 |
+
v_rfl.lo['EX_cpd00069_e0'] = -0.218417727 * 4.55 # uptake rate for L-Tyrosine
|
| 276 |
+
v_prm.lo['EX_cpd00060_e0'] = -0.233929798 * 4.55 # uptake rate for L-Methionine
|
| 277 |
+
v_prm.lo['EX_cpd00161_e0'] = -0.261179221 * 4.55 # uptake rate for L-Threonine
|
| 278 |
+
v_rfl.lo['EX_cpd00161_e0'] = -0.261179221 * 4.55
|
| 279 |
+
v_rfl.lo['EX_cpd00322_e0'] = -0.211165444 * 4.55 # uptake rate for L-Isoleucine
|
| 280 |
+
v_prm.lo['EX_cpd00051_e0'] = -0.133660701 * 4.55 # uptake rate for L-Arginine
|
| 281 |
+
v_rfl.lo['EX_cpd00051_e0'] = -0.133660701 * 4.55
|
| 282 |
+
# v_prm.lo['EX_cpd00033_e0'] = -0.268595078 * 4.55 # uptake rate for Glycine ******
|
| 283 |
+
# v_rfl.lo['EX_cpd00033_e0'] = -0.268595078 * 4.55
|
| 284 |
+
v_prm.lo['EX_cpd00348_e0'] = -0.075513967 * 4.55 # uptake rate for D-Galactose
|
| 285 |
+
v_rfl.lo['EX_cpd00348_e0'] = -0.075513967 * 4.55
|
| 286 |
+
v_rfl.lo['EX_cpd00119_e0'] = -0.124559013 * 4.55 # uptake rate for L-Histidine
|
| 287 |
+
v_prm.lo['EX_cpd00039_e0'] = -0.098373937 * 4.55 # uptake rate for L-Lysine
|
| 288 |
+
v_rfl.lo['EX_cpd00039_e0'] = -0.098373937 * 4.55
|
| 289 |
+
v_prm.lo['EX_cpd00084_e0'] = -0.114920408 * 4.55 # uptake rate for L-Cysteine
|
| 290 |
+
v_rfl.lo['EX_cpd00084_e0'] = -0.114920408 * 4.55
|
| 291 |
+
v_prm.lo['EX_cpd00053_e0'] = -0.080568485 * 4.55 # uptake rate for L-Glutamine
|
| 292 |
+
v_rfl.lo['EX_cpd00053_e0'] = -0.080568485 * 4.55
|
| 293 |
+
v_rfl.lo['EX_cpd00038_e0'] = -0.007734655 * 4.55 # uptake rate for GTP
|
| 294 |
+
v_rfl.lo['EX_cpd00138_e0'] = -0.021731242 * 4.55 # uptake rate for D-Mannose
|
| 295 |
+
v_prm.lo['EX_cpd00052_e0'] = -0.007307850 * 4.55 # uptake rate for CTP
|
| 296 |
+
v_rfl.lo['EX_cpd00052_e0'] = -0.007307850 * 4.55
|
| 297 |
+
v_prm.lo['EX_cpd00002_e0'] = -0.006289719 * 4.55 # uptake rate for ATP
|
| 298 |
+
v_rfl.lo['EX_cpd00002_e0'] = -0.006289719 * 4.55
|
| 299 |
+
v_prm.lo['EX_cpd00062_e0'] = -0.005932755 * 4.55 # uptake rate for UTP
|
| 300 |
+
v_rfl.lo['EX_cpd00062_e0'] = -0.005932755 * 4.55
|
| 301 |
+
v_rfl.lo['EX_cpd00115_e0'] = -0.001147315 * 4.55 # uptake rate for dATP
|
| 302 |
+
v_rfl.lo['EX_cpd00357_e0'] = -0.001147552 * 4.55 # uptake rate for dTTP
|
| 303 |
+
v_rfl.lo['EX_cpd00241_e0'] = -0.001012678 * 4.55 # uptake rate for dGTP
|
| 304 |
+
v_prm.lo['EX_cpd00356_e0'] = -0.001016235 * 4.55 # uptake rate for dCTP
|
| 305 |
+
v_rfl.lo['EX_cpd00356_e0'] = -0.001016235 * 4.55
|
| 306 |
+
# v_prm.lo['EX_cpd11746_e0'] = -0.320930655 * 4.55 # uptake rate for Cellulose ****
|
| 307 |
+
v_rfl.lo['EX_cpd11746_e0'] = -0.320930655 * 4.55
|
| 308 |
+
v_rfl.lo['EX_cpd29869_e0'] = -0.002499522 * 4.55 # uptake rate for hemicellulose
|
| 309 |
+
# v_prm.lo['EX_cpd00009_e0'] = -0.005244478 * 4.55 # uptake rate for Phosphate, this is an inorganic ion, uptake set to max
|
| 310 |
+
# v_rfl.lo['EX_cpd00009_e0'] = -0.005244478 * 4.55
|
| 311 |
+
v_rfl.lo['EX_cpd00065_e0'] = 0 # uptake rate for Tryptophan
|
| 312 |
+
v_prm.lo['EX_cpd00073_e0'] = -0.629166662 * 4.55 # uptake rate for Urea
|
| 313 |
+
v_rfl.lo['EX_cpd00073_e0'] = -0.629166662 * 4.55
|
| 314 |
+
# v_prm.lo['EX_cpd00048_e0'] = -0.004273279 * 4.55 # uptake rate for Sulfate, this is an inorganic ion, uptake set to max
|
| 315 |
+
# v_rfl.lo['EX_cpd00048_e0'] = -0.004273279 * 4.55
|
| 316 |
+
|
| 317 |
+
# added constraints to bring down the MGK flux
|
| 318 |
+
v_mgk.lo['EX_cpd00162_e0'] = -1 # uptake rate for aminoethanol
|
| 319 |
+
v_mgk.lo['EX_cpd00122_e0'] = -0.01 # uptake rate for n-acetyl-D-glucosamine
|
| 320 |
+
|
| 321 |
+
# added contraints to coorespond to the different treatment options
|
| 322 |
+
# COMBINED APPROACH: Apply both docking-based constraints AND literature-based constraints
|
| 323 |
+
# Docking captures direct enzyme effects, literature captures indirect community effects
|
| 324 |
+
|
| 325 |
+
if methane == 'variable':
|
| 326 |
+
# Apply docking-based constraints (direct enzyme effects)
|
| 327 |
+
docking_applied = False
|
| 328 |
+
if treatment != 'no':
|
| 329 |
+
try:
|
| 330 |
+
from docking_integration.apply_docking_constraints import apply_docking_treatment
|
| 331 |
+
import os
|
| 332 |
+
|
| 333 |
+
docking_file = 'docking_data/cleaned_docking_results.csv'
|
| 334 |
+
if os.path.exists(docking_file):
|
| 335 |
+
# Map treatment names to molecule names in docking file
|
| 336 |
+
molecule_map = {
|
| 337 |
+
'imidazole': 'Imidazole',
|
| 338 |
+
'l-carnitine': 'L-carnitine',
|
| 339 |
+
'methyl jasmonate': 'Methyl jasmonate',
|
| 340 |
+
'propylpyrazine': 'Propylpyrazine'
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
if treatment in molecule_map:
|
| 344 |
+
molecule_name = molecule_map[treatment]
|
| 345 |
+
apply_docking_treatment(
|
| 346 |
+
v_mgk, v_prm, v_rfl,
|
| 347 |
+
molecule_name=molecule_name,
|
| 348 |
+
docking_csv_path=docking_file,
|
| 349 |
+
methane=methane
|
| 350 |
+
)
|
| 351 |
+
docking_applied = True
|
| 352 |
+
print(f"Docking-based constraints applied for {treatment}")
|
| 353 |
+
except Exception as e:
|
| 354 |
+
print(f"Warning: Could not apply docking constraints: {e}")
|
| 355 |
+
docking_applied = False
|
| 356 |
+
|
| 357 |
+
# ALWAYS apply literature-based constraints (indirect community effects)
|
| 358 |
+
# These capture mechanisms that docking might miss (community interactions, etc.)
|
| 359 |
+
if treatment == 'imidazole':
|
| 360 |
+
# reactions that are affected by imidazole treatment
|
| 361 |
+
# Imidazole inhibits lysozyme activity in protozoa, reducing their ability to digest bacteria
|
| 362 |
+
# This reduces predation pressure on bacteria, allowing them to grow more freely
|
| 363 |
+
# We simulate this by increasing biomass production rates and reducing some metabolic constraints
|
| 364 |
+
|
| 365 |
+
# Increase biomass production rates for all bacteria (reduced predation pressure)
|
| 366 |
+
v_mgk.lo['R_biomass0'] = v_mgk.lo['R_biomass0'] * 1.15 # Increase biomass production by 15%
|
| 367 |
+
v_prm.lo['R_biomass0'] = v_prm.lo['R_biomass0'] * 1.15
|
| 368 |
+
v_rfl.lo['R_biomass0'] = v_rfl.lo['R_biomass0'] * 1.15
|
| 369 |
+
# Increase substrate uptake rates (bacteria can access more resources with reduced predation)
|
| 370 |
+
# Note: We'll use more conservative increases and only apply to reactions that exis
|
| 371 |
+
# v_prm.lo['EX_cpd00027_e0'] = v_prm.lo['EX_cpd00027_e0'] * 1.2
|
| 372 |
+
# v_rfl.lo['EX_cpd00027_e0'] = v_rfl.lo['EX_cpd00027_e0'] * 1.2
|
| 373 |
+
# Increase acetate production (common byproduct of bacterial metabolism)
|
| 374 |
+
v_mgk.lo['EX_cpd00029_e0'] = v_mgk.lo['EX_cpd00029_e0'] * 1.1
|
| 375 |
+
v_prm.lo['EX_cpd00029_e0'] = v_prm.lo['EX_cpd00029_e0'] * 1.1
|
| 376 |
+
v_rfl.lo['EX_cpd00029_e0'] = v_rfl.lo['EX_cpd00029_e0'] * 1.1
|
| 377 |
+
# Increase formate production (important for methanogenesis)
|
| 378 |
+
# v_mgk.lo['EX_cpd00056_e0'] = v_mgk.lo['EX_cpd00056_e0'] * 1.2
|
| 379 |
+
# v_prm.lo['EX_cpd00056_e0'] = v_prm.lo['EX_cpd00056_e0'] * 1.2
|
| 380 |
+
# v_rfl.lo['EX_cpd00056_e0'] = v_rfl.lo['EX_cpd00056_e0'] * 1.2
|
| 381 |
+
# Increase H2 production (important substrate for methanogenesis)
|
| 382 |
+
v_mgk.lo['EX_cpd00067_e0'] = v_mgk.lo['EX_cpd00067_e0'] * 1.25
|
| 383 |
+
v_prm.lo['EX_cpd00067_e0'] = v_prm.lo['EX_cpd00067_e0'] * 1.25
|
| 384 |
+
v_rfl.lo['EX_cpd00067_e0'] = v_rfl.lo['EX_cpd00067_e0'] * 1.25
|
| 385 |
+
print("Literature-based constraints applied for imidazole (community effects)")
|
| 386 |
+
elif treatment == 'l-carnitine':
|
| 387 |
+
# reactions that are affected by l-carnitine treatment
|
| 388 |
+
v_mgk.lo['EX_cpd01188_e0'] = -0.009476130618701499 * 0.89 # output rate for lanosterol, 0.87 times the original value becase cholesterol falls
|
| 389 |
+
v_rfl.lo['EX_cpd01188_e0'] = -0.01658854044409092 * 0.89
|
| 390 |
+
print("Literature-based constraints applied for l-carnitine")
|
| 391 |
+
elif treatment == 'methyl jasmonate':
|
| 392 |
+
print("Methyl jasmonate treatment selected, setting constraints...")
|
| 393 |
+
v_mgk.lo['EX_cpd00129_e0'] = 0.01608686252400516 * 1.23 # output rate for proline, 1.23 times the original value based on Lubyanova paper
|
| 394 |
+
v_prm.lo['EX_cpd00129_e0'] = 0.004029898865569517 * 1.23
|
| 395 |
+
# v_mgk.lo['R_rxn09296_c0'] = 0.0005201736148737044 * 1.4 # H2O2 reduction by thioredoxin, 1.4 times the original value based on Lubyanova paper
|
| 396 |
+
# v_prm.lo['R_rxn09296_c0'] = 71.50423813116777 * 1.4
|
| 397 |
+
# v_rfl.lo['R_rxn09296_c0'] = 316.9770835412888 * 1.4
|
| 398 |
+
# v_prm.lo['R_rxn12638_c0'] = 65.98723846787729 * 1.23 # breakdown of N-glycylproline
|
| 399 |
+
print("Literature-based constraints applied for methyl jasmonate")
|
| 400 |
+
elif treatment == 'propylpyrazine':
|
| 401 |
+
# reactions that are affected by propylpyrazine treatment
|
| 402 |
+
# v_mgk.lo['R_rxn00305_c0'] = 191.07533512418465 * 3.02 # Pck1 expression went up about 3 times after treatment with TMP, should affect GTP and phosphoenolpyruvate
|
| 403 |
+
# v_prm.lo['R_rxn00305_c0'] = 169.79210656337526 * 3.02
|
| 404 |
+
# v_rfl.lo['R_rxn00305_c0'] = 164.67010537093077 * 3.02
|
| 405 |
+
# v_mgk.lo['R_rxn00285_c0'] = 0.0011420124768651806 * 2.14 # Sucla2 expression went up about 2.14 times after treatment with propylpyrazine, should affect succinyl-CoA
|
| 406 |
+
# v_rfl.lo['R_rxn00285_c0'] = 0.012806125516892619 * 2.14
|
| 407 |
+
# v_mgk.lo['R_rxn12510_c0'] = 0.0010308604158823106 * 1.77 # Pank1 expression went up about 1.77 times after treatment with propylpyrazine, should affect phosphorylation of pantothenate
|
| 408 |
+
# v_prm.lo['R_rxn12510_c0'] = 0.008928357454568775 * 1.77
|
| 409 |
+
# v_rfl.lo['R_rxn12510_c0'] = 0.0015697141164147958 * 1.77
|
| 410 |
+
# v_prm.lo['R_rxn00248_c0'] = 167.2035577959039 * 1.93 # Mdh2 went up about 1.93 times after treatment with propylpyrazine, should affect conversion of L-malate to oxaloacetate
|
| 411 |
+
# v_mgk.lo['R_rxn06037_c0'] = -6.170993629588869e-21 * 3.08 # Hadhb expression went up about 3.08 times after treatment with propylpyrazine, should affect conversion of 3-hydroxyacyl-CoA -> 3-oxoacyl-CoA
|
| 412 |
+
# v_prm.lo['R_rxn00799_c0'] = 127.86504315656339 * 2.19 # Fh1 expression went up about 2.19 times after treatment with propylpyrazine, should affect conversion of fumarate to L-malate
|
| 413 |
+
# v_rfl.lo['R_rxn00256_c0'] = 104.25331895829011 * 1.43 # Cs expression went up about 1.43 times after treatment with propylpyrazine, should affect conversion of oxaloacetate to citrate
|
| 414 |
+
v_mgk.lo['R_rxn12512_c0'] = 0.000453718935224341 * 1.17 # Ppcs expression went up about 1.17 times after treatment with propylpyrazine, should affect conversion of phosphopantothenate combination with cysteine
|
| 415 |
+
v_prm.lo['R_rxn12512_c0'] = 0.004463845288178093 * 1.17
|
| 416 |
+
v_rfl.lo['R_rxn12512_c0'] = 0.0007848557326249302 * 1.17
|
| 417 |
+
print("Literature-based constraints applied for propylpyrazine")
|
| 418 |
+
elif treatment == 'no':
|
| 419 |
+
# no treatment, no additional constraints
|
| 420 |
+
print("No treatment selected, using default constraints.")
|
| 421 |
+
elif methane == 'fixed':
|
| 422 |
+
if treatment == 'imidazole':
|
| 423 |
+
# reactions that are affected by imidazole treatment
|
| 424 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.74 * 2.5125e-5 # output rate for methane based on USDA data, conversion factor from ml to mmol/gDCW.hr
|
| 425 |
+
print("Imidazole treatment selected, setting constraints...")
|
| 426 |
+
elif treatment == 'l-carnitine':
|
| 427 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.79 * 2.5125e-5
|
| 428 |
+
# reactions that are affected by l-carnitine treatment
|
| 429 |
+
print("L-carnitine treatment selected, setting constraints...")
|
| 430 |
+
elif treatment == 'methyl jasmonate':
|
| 431 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.53 * 2.5125e-5
|
| 432 |
+
print("Methyl jasmonate treatment selected, setting constraints...")
|
| 433 |
+
elif treatment == 'propylpyrazine':
|
| 434 |
+
v_mgk.fx['EX_cpd01024_e0'] = 4.40 * 2.5125e-5
|
| 435 |
+
# reactions that are affected by propylpyrazine treatment
|
| 436 |
+
print("Propylpyrazine treatment selected, setting constraints...")
|
| 437 |
+
elif treatment == 'no':
|
| 438 |
+
# no treatment, no additional constraints
|
| 439 |
+
v_mgk.fx['EX_cpd01024_e0'] = 3.40 * 2.5125e-5
|
| 440 |
+
print("No treatment selected, using default constraints.")
|
| 441 |
+
|
| 442 |
+
# Dual variables for bounds
|
| 443 |
+
global muLB_mgk, muUB_mgk, muLB_prm, muUB_prm, muLB_rfl, muUB_rfl
|
| 444 |
+
|
| 445 |
+
muLB_mgk = Variable(container=cowmunity, name="muLB_mgk", domain=j_mgk, description="Dual variables for MGK LB")
|
| 446 |
+
muUB_mgk = Variable(container=cowmunity, name="muUB_mgk", domain=j_mgk, description="Dual variables for MGK UB")
|
| 447 |
+
muLB_prm = Variable(container=cowmunity, name="muLB_prm", domain=j_prm, description="Dual variables for PRM LB")
|
| 448 |
+
muUB_prm = Variable(container=cowmunity, name="muUB_prm", domain=j_prm, description="Dual variables for PRM UB")
|
| 449 |
+
muLB_rfl = Variable(container=cowmunity, name="muLB_rfl", domain=j_rfl, description="Dual variables for RFL LB")
|
| 450 |
+
muUB_rfl = Variable(container=cowmunity, name="muUB_rfl", domain=j_rfl, description="Dual variables for RFL UB")
|
| 451 |
+
|
| 452 |
+
# Set dual variables to positive
|
| 453 |
+
muLB_mgk.lo[j_mgk] = 0
|
| 454 |
+
muUB_mgk.lo[j_mgk] = 0
|
| 455 |
+
muLB_prm.lo[j_prm] = 0
|
| 456 |
+
muUB_prm.lo[j_prm] = 0
|
| 457 |
+
muLB_rfl.lo[j_rfl] = 0
|
| 458 |
+
muUB_rfl.lo[j_rfl] = 0
|
| 459 |
+
|
| 460 |
+
# transfer uptake positive variables for the shared metabolites
|
| 461 |
+
|
| 462 |
+
global trans_CO2_mgk, trans_H2_mgk, trans_formate_mgk, trans_acetate_mgk, trans_d_mannose_mgk, trans_d_fructose_mgk, trans_tetrathionate_mgk, trans_thiosulfate_mgk
|
| 463 |
+
global trans_cellulose_prm, trans_d_glucose_prm, trans_acetate_prm, trans_l_arabinose_prm, trans_biotin_prm, trans_thiamin_prm, trans_octadecenoate_prm, trans_maltoheptaose_prm
|
| 464 |
+
global trans_nitrite_prm, trans_n_acetyl_d_glucosamine_prm, trans_aminoethanol_prm, trans_cobinamide_prm, trans_alanine_prm, trans_leucine_prm, trans_glycine_prm, trans_proline_prm
|
| 465 |
+
global trans_d_galacturonate_rfl, trans_deoxyadenosine_rfl, trans_dephospho_coa_rfl, trans_cobinamide_rfl, trans_alanine_rfl, trans_leucine_rfl, trans_glycine_rfl, trans_proline_rfl, trans_aminoethanol_rfl
|
| 466 |
+
|
| 467 |
+
trans_CO2_mgk = Variable(container=cowmunity, name="trans_CO2_mgk", description="maximum transfer of CO2 to M. Gottschalkii")
|
| 468 |
+
trans_H2_mgk = Variable(container=cowmunity, name="trans_H2_mgk", description="maximum transfer of H2 to M. Gottschalkii")
|
| 469 |
+
trans_formate_mgk = Variable(container=cowmunity, name='trans_formate_mgk', description="maximum transfer of formate to M. Gottschalkii")
|
| 470 |
+
trans_acetate_mgk = Variable(container=cowmunity, name="trans_acetate_mgk", description="maximum transfer of acetate to M. Gottschalkii")
|
| 471 |
+
trans_d_mannose_mgk = Variable(container=cowmunity, name="trans_dmannose_mgk", description="maximum transfer of D-mannose to M. Gottschalkii")
|
| 472 |
+
trans_d_fructose_mgk = Variable(container=cowmunity, name="trans_dfructose_mgk", description="maximum transfer of D-fructose to M. Gottschalkii")
|
| 473 |
+
trans_tetrathionate_mgk = Variable(container=cowmunity, name="trans_tetrathionate_mgk", description="maximum transfer of tetrathionate to M. Gottschalkii")
|
| 474 |
+
trans_thiosulfate_mgk = Variable(container=cowmunity, name="trans_thiosulfate_mgk", description="maximum transfer of thiosulfate to M. Gottschalkii")
|
| 475 |
+
|
| 476 |
+
trans_cellulose_prm = Variable(container=cowmunity, name='trans_cellulose_prm', description="maximum transfer of cellulose to P. ruminicola")
|
| 477 |
+
trans_d_glucose_prm = Variable(container=cowmunity, name='trans_d_glucose_prm', description="maximum transfer of D-Glucose to P. ruminicola")
|
| 478 |
+
trans_acetate_prm = Variable(container=cowmunity, name='trans_acetate_prm', description="maximum transfer of Acetate to P. ruminicola")
|
| 479 |
+
trans_l_arabinose_prm = Variable(container=cowmunity, name='trans_l_arabinose_prm', description="maximum transfer of L-Arabinose to P. ruminicola")
|
| 480 |
+
trans_biotin_prm = Variable(container=cowmunity, name='trans_biotin_prm', description="maximum transfer of Biotin to P. ruminicola")
|
| 481 |
+
trans_thiamin_prm = Variable(container=cowmunity, name='trans_thiamin_prm', description="maximum transfer of Thiamin to P. ruminicola")
|
| 482 |
+
trans_octadecenoate_prm = Variable(container=cowmunity, name='trans_octadecenoate_prm', description="maximum transfer of octadecenoate to P. ruminicola")
|
| 483 |
+
trans_maltoheptaose_prm = Variable(container=cowmunity, name='trans_maltoheptaose_prm', description="maximum transfer of Maltoheptaose to P. ruminicola")
|
| 484 |
+
trans_nitrite_prm = Variable(container=cowmunity, name='trans_nitrite_prm', description="maximum transfer of Nitrite to P. ruminicola")
|
| 485 |
+
trans_n_acetyl_d_glucosamine_prm = Variable(container=cowmunity, name='trans_n_acetyl_d_glucosamine_prm', description="maximum transfer of N-Acetyl-D-glucosamine to P. ruminicola")
|
| 486 |
+
trans_aminoethanol_prm = Variable(container=cowmunity, name='trans_aminoethanol_prm', description="maximum transfer of Aminoethanol to P. ruminicola")
|
| 487 |
+
trans_cobinamide_prm = Variable(container=cowmunity, name='trans_cobinamide_prm', description="maximum transfer of Cobinamide to P. ruminicola")
|
| 488 |
+
trans_alanine_prm = Variable(container=cowmunity, name='trans_alanine_prm', description="maximum transfer of Alanine to P. ruminicola")
|
| 489 |
+
trans_leucine_prm = Variable(container=cowmunity, name='trans_leucine_prm', description="maximum transfer of Leucine to P. ruminicola")
|
| 490 |
+
trans_glycine_prm = Variable(container=cowmunity, name='trans_glycine_prm', description="maximum transfer of Glycine to P. ruminicola")
|
| 491 |
+
trans_proline_prm = Variable(container=cowmunity, name='trans_proline_prm', description="maximum transfer of Proline to P. ruminicola")
|
| 492 |
+
|
| 493 |
+
trans_d_galacturonate_rfl = Variable(container=cowmunity, name='trans_d_galacturonate_rfl', description="maximum transfer of D-Galacturonate to R. flavefaciens")
|
| 494 |
+
trans_deoxyadenosine_rfl = Variable(container=cowmunity, name='trans_deoxyadenosine_rfl', description="maximum transfer of Deoxyadenosine to R. flavefaciens")
|
| 495 |
+
trans_dephospho_coa_rfl = Variable(container=cowmunity, name='trans_dephospho_coa_rfl', description="maximum transfer of Dephospho-CoA to R. flavefaciens")
|
| 496 |
+
trans_cobinamide_rfl = Variable(container=cowmunity, name='trans_cobinamide_rfl', description="maximum transfer of Cobinamide to R. flavefaciens")
|
| 497 |
+
trans_alanine_rfl = Variable(container=cowmunity, name='trans_alanine_rfl', description="maximum transfer of Alanine to R. flavefaciens")
|
| 498 |
+
trans_leucine_rfl = Variable(container=cowmunity, name='trans_leucine_rfl', description="maximum transfer of Leucine to R. flavefaciens")
|
| 499 |
+
trans_glycine_rfl = Variable(container=cowmunity, name='trans_glycine_rfl', description="maximum transfer of Glycine to R. flavefaciens")
|
| 500 |
+
trans_proline_rfl = Variable(container=cowmunity, name='trans_proline_rfl', description="maximum transfer of Proline to R. flavefaciens")
|
| 501 |
+
trans_aminoethanol_rfl = Variable(container=cowmunity, name='trans_aminoethanol_rfl', description="maximum transfer of Aminoethanol to R. flavefaciens")
|
| 502 |
+
|
| 503 |
+
# set the transfer variables to positive, these are the maximum transfer rates for each metabolite
|
| 504 |
+
|
| 505 |
+
trans_CO2_mgk.lo = 0
|
| 506 |
+
trans_H2_mgk.lo = 0
|
| 507 |
+
trans_formate_mgk.lo = 0
|
| 508 |
+
trans_acetate_mgk.lo = 0
|
| 509 |
+
trans_d_mannose_mgk.lo = 0
|
| 510 |
+
trans_d_fructose_mgk.lo = 0
|
| 511 |
+
trans_tetrathionate_mgk.lo = 0
|
| 512 |
+
trans_thiosulfate_mgk.lo = 0
|
| 513 |
+
|
| 514 |
+
trans_cellulose_prm.lo = 0
|
| 515 |
+
trans_d_glucose_prm.lo = 0
|
| 516 |
+
trans_acetate_prm.lo = 0
|
| 517 |
+
trans_l_arabinose_prm.lo = 0
|
| 518 |
+
trans_biotin_prm.lo = 0
|
| 519 |
+
trans_thiamin_prm.lo = 0
|
| 520 |
+
trans_octadecenoate_prm.lo = 0
|
| 521 |
+
trans_maltoheptaose_prm.lo = 0
|
| 522 |
+
trans_nitrite_prm.lo = 0
|
| 523 |
+
trans_n_acetyl_d_glucosamine_prm.lo = 0
|
| 524 |
+
trans_aminoethanol_prm.lo = 0
|
| 525 |
+
trans_cobinamide_prm.lo = 0
|
| 526 |
+
trans_alanine_prm.lo = 0
|
| 527 |
+
trans_leucine_prm.lo = 0
|
| 528 |
+
trans_glycine_prm.lo = 0
|
| 529 |
+
trans_proline_prm.lo = 0
|
| 530 |
+
|
| 531 |
+
trans_d_galacturonate_rfl.lo = 0
|
| 532 |
+
trans_deoxyadenosine_rfl.lo = 0
|
| 533 |
+
trans_dephospho_coa_rfl.lo = 0
|
| 534 |
+
trans_cobinamide_rfl.lo = 0
|
| 535 |
+
trans_alanine_rfl.lo = 0
|
| 536 |
+
trans_leucine_rfl.lo = 0
|
| 537 |
+
trans_glycine_rfl.lo = 0
|
| 538 |
+
trans_proline_rfl.lo = 0
|
| 539 |
+
trans_aminoethanol_rfl.lo = 0
|
| 540 |
+
|
| 541 |
+
def Equations():
|
| 542 |
+
print("Adding equations...")
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
# Objective Functions (Outer Objective)
|
| 546 |
+
biomass_objective = Equation(container=cowmunity, name="biomass_objective", description="Objective function for total biomass accumulation")
|
| 547 |
+
biomass_objective[...] = biomass_outer == v_mgk['R_biomass0'] + v_prm['R_biomass0'] + v_rfl['R_biomass0']
|
| 548 |
+
|
| 549 |
+
ATP_objective = Equation(container=cowmunity, name="ATP_objective", description="Objective function for total ATP Production")
|
| 550 |
+
ATP_objective[...] = ATP_outer == v_mgk['R_rxn02831_c0'] + v_mgk['R_rxn03535_c0'] + v_mgk['R_rxn06874_c0'] + v_mgk['R_rxn10476_c0'] + v_mgk['R_rxn11544_c0'] \
|
| 551 |
+
+ v_prm['R_rxn00986_c0'] + v_prm['R_rxn01987_c0'] + v_prm['R_rxn10042_c0'] \
|
| 552 |
+
+ v_rfl['R_rxn05840_c0'] + v_rfl['R_rxn06428_c0'] + v_rfl['R_rxn06874_c0'] + v_rfl['R_rxn10042_c0']
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
# Constraints
|
| 556 |
+
# these are the things that are going to make the model into a true community model rather than three separate models
|
| 557 |
+
|
| 558 |
+
trans_CO2_mgk_balance = Equation(container=cowmunity, name='trans_CO2_balance', description="Balance for CO2 transfer to M. Gottschalkii")
|
| 559 |
+
trans_CO2_mgk_balance[...] = trans_CO2_mgk <= v_prm['EX_cpd00011_e0'] + v_rfl['EX_cpd00011_e0']
|
| 560 |
+
|
| 561 |
+
trans_H2_mgk_balance = Equation(container=cowmunity, name= 'trans_H2_mgk_balance', description="Balance for H2 transfer to M. Gottschalkii")
|
| 562 |
+
trans_H2_mgk_balance[...] = trans_H2_mgk <= v_prm['EX_cpd11640_e0'] + v_rfl['EX_cpd11640_e0']
|
| 563 |
+
|
| 564 |
+
trans_formate_mgk_balance = Equation(container=cowmunity, name='trans_formate_mgk_balance', description="Balance for formate transfer to M. Gottschalkii")
|
| 565 |
+
trans_formate_mgk_balance[...] = trans_formate_mgk <= v_prm['EX_cpd00047_e0'] + v_rfl['EX_cpd00047_e0']
|
| 566 |
+
|
| 567 |
+
trans_acetate_mgk_balance = Equation(container=cowmunity, name='trans_acetate_mgk_balance', description="Balance for acetate transfer to M. Gottschalkii")
|
| 568 |
+
trans_acetate_mgk_balance[...] = trans_acetate_mgk <= v_rfl['EX_cpd00029_e0']
|
| 569 |
+
|
| 570 |
+
trans_d_mannose_mgk_balance = Equation(container=cowmunity, name='trans_d_mannose_mgk_balance', description="Balance for D-mannose transfer to M. Gottschalkii")
|
| 571 |
+
trans_d_mannose_mgk_balance[...] = trans_d_mannose_mgk <= v_rfl['EX_cpd00138_e0']
|
| 572 |
+
|
| 573 |
+
trans_d_fructose_mgk_balance = Equation(container=cowmunity, name='trans_d_fructose_mgk_balance', description="Balance for D-fructose transfer to M. Gottschalkii")
|
| 574 |
+
trans_d_fructose_mgk_balance[...] = trans_d_fructose_mgk <= v_rfl['EX_cpd00082_e0']
|
| 575 |
+
|
| 576 |
+
trans_tetrathionate_mgk_balance = Equation(container=cowmunity, name='trans_tetrathionate_mgk_balance', description="Balance for tetrathionate transfer to M. Gottschalkii")
|
| 577 |
+
trans_tetrathionate_mgk_balance[...] = trans_tetrathionate_mgk <= v_rfl['EX_cpd01414_e0']
|
| 578 |
+
|
| 579 |
+
trans_thiosulfate_mgk_balance = Equation(container=cowmunity, name='trans_thiosulfate_mgk_balance', description="Balance for thiosulfate transfer to M. Gottschalkii")
|
| 580 |
+
trans_thiosulfate_mgk_balance[...] = trans_thiosulfate_mgk <= v_prm['EX_cpd00268_e0']
|
| 581 |
+
|
| 582 |
+
trans_cellulose_prm_balance = Equation(container=cowmunity, name='trans_cellulose_prm_balance', description="Balance for cellulose transfer to P. ruminicola")
|
| 583 |
+
trans_cellulose_prm_balance[...] = trans_cellulose_prm <= v_rfl['EX_cpd11746_e0']
|
| 584 |
+
|
| 585 |
+
trans_d_glucose_prm_balance = Equation(container=cowmunity, name='trans_d_glucose_prm_balance', description="Balance for D-glucose transfer to P. ruminicola")
|
| 586 |
+
trans_d_glucose_prm_balance[...] = trans_d_glucose_prm <= v_rfl['EX_cpd00027_e0']
|
| 587 |
+
|
| 588 |
+
trans_acetate_prm_balance = Equation(container=cowmunity, name='trans_acetate_prm_balance', description="Balance for acetate transfer to P. ruminicola")
|
| 589 |
+
trans_acetate_prm_balance[...] = trans_acetate_prm <= v_rfl['EX_cpd00029_e0']
|
| 590 |
+
|
| 591 |
+
trans_l_arabinose_prm_balance = Equation(container=cowmunity, name='trans_l_arabinose_prm_balance', description="Balance for L-arabinose transfer to P. ruminicola")
|
| 592 |
+
trans_l_arabinose_prm_balance[...] = trans_l_arabinose_prm <= v_rfl['EX_cpd00224_e0']
|
| 593 |
+
|
| 594 |
+
trans_biotin_prm_balance = Equation(container=cowmunity, name='trans_biotin_prm_balance', description="Balance for biotin transfer to P. ruminicola")
|
| 595 |
+
trans_biotin_prm_balance[...] = trans_biotin_prm <= v_rfl['EX_cpd00104_e0']
|
| 596 |
+
|
| 597 |
+
# ****** commented to preserve RFL FLux ********* trans_thiamin_prm_balance = Equation(container=cowmunity, name='trans_thiamin_prm_balance', description="Balance for thiamin transfer to P. ruminicola")
|
| 598 |
+
# ****** commented to preserve RFL FLux ********* trans_thiamin_prm_balance[...] = trans_thiamin_prm <= v_rfl['EX_cpd00305_e0']
|
| 599 |
+
|
| 600 |
+
trans_octadecenoate_prm_balance = Equation(container=cowmunity, name='trans_octadecenoate_prm_balance', description="Balance for octadecenoate transfer to P. ruminicola")
|
| 601 |
+
trans_octadecenoate_prm_balance[...] = trans_octadecenoate_prm <= v_rfl['EX_cpd15269_e0'] + v_mgk['EX_cpd15269_e0']
|
| 602 |
+
|
| 603 |
+
trans_maltoheptaose_prm_balance = Equation(container=cowmunity, name='trans_maltoheptaose_prm_balance', description="Balance for maltoheptaose transfer to P. ruminicola")
|
| 604 |
+
trans_maltoheptaose_prm_balance[...] = trans_maltoheptaose_prm <= v_rfl['EX_cpd15494_e0']
|
| 605 |
+
|
| 606 |
+
trans_nitrite_prm_balance = Equation(container=cowmunity, name='trans_nitrite_prm_balance', description="Balance for nitrite transfer to P. ruminicola")
|
| 607 |
+
trans_nitrite_prm_balance[...] = trans_nitrite_prm <= v_mgk['EX_cpd00075_e0']
|
| 608 |
+
|
| 609 |
+
# ****** commented to preserve MGK FLux ********* trans_n_acetyl_d_glucosamine_prm_balance = Equation(container=cowmunity, name='trans_n_acetyl_d_glucosamine_prm_balance', description="Balance for N-acetyl-D-glucosamine transfer to P. ruminicola")
|
| 610 |
+
# ****** commented to preserve MGK FLux ********* trans_n_acetyl_d_glucosamine_prm_balance[...] = trans_n_acetyl_d_glucosamine_prm <= v_mgk['EX_cpd00122_e0']
|
| 611 |
+
|
| 612 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_prm_balance = Equation(container=cowmunity, name='trans_aminoethanol_prm_balance', description="Balance for aminoethanol transfer to P. ruminicola")
|
| 613 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_prm_balance[...] = trans_aminoethanol_prm <= v_mgk['EX_cpd00162_e0']
|
| 614 |
+
|
| 615 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_prm_balance = Equation(container=cowmunity, name='trans_cobinamide_prm_balance', description="Balance for cobinamide transfer to P. ruminicola")
|
| 616 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_prm_balance[...] = trans_cobinamide_prm <= v_mgk['EX_cpd03422_e0']
|
| 617 |
+
|
| 618 |
+
trans_alanine_prm_balance = Equation(container=cowmunity, name='trans_alanine_prm_balance', description="Balance for alanine transfer to P. ruminicola")
|
| 619 |
+
trans_alanine_prm_balance[...] = trans_alanine_prm <= v_mgk['EX_cpd00035_e0']
|
| 620 |
+
|
| 621 |
+
trans_leucine_prm_balance = Equation(container=cowmunity, name='trans_leucine_prm_balance', description="Balance for leucine transfer to P. ruminicola")
|
| 622 |
+
trans_leucine_prm_balance[...] = trans_leucine_prm <= v_mgk['EX_cpd00107_e0']
|
| 623 |
+
|
| 624 |
+
trans_glycine_prm_balance = Equation(container=cowmunity, name='trans_glycine_prm_balance', description="Balance for glycine transfer to P. ruminicola")
|
| 625 |
+
trans_glycine_prm_balance[...] = trans_glycine_prm <= v_mgk['EX_cpd00033_e0']
|
| 626 |
+
|
| 627 |
+
trans_proline_prm_balance = Equation(container=cowmunity, name='trans_proline_prm_balance', description="Balance for proline transfer to P. ruminicola")
|
| 628 |
+
trans_proline_prm_balance[...] = trans_proline_prm <= v_mgk['EX_cpd00129_e0']
|
| 629 |
+
|
| 630 |
+
trans_d_galacturonate_rfl_balance = Equation(container=cowmunity, name='trans_d_galacturonate_rfl_balance', description="Balance for D-galacturonate transfer to R. flavefaciens")
|
| 631 |
+
trans_d_galacturonate_rfl_balance[...] = trans_d_galacturonate_rfl <= v_prm['EX_cpd00280_e0']
|
| 632 |
+
|
| 633 |
+
trans_deoxyadenosine_rfl_balance = Equation(container=cowmunity, name='trans_deoxyadenosine_rfl_balance', description="Balance for deoxyadenosine transfer to R. flavefaciens")
|
| 634 |
+
trans_deoxyadenosine_rfl_balance[...] = trans_deoxyadenosine_rfl <= v_prm['EX_cpd00438_e0']
|
| 635 |
+
|
| 636 |
+
trans_dephospho_coa_rfl_balance = Equation(container=cowmunity, name='trans_dephospho_coa_rfl_balance', description="Balance for dephospho-CoA transfer to R. flavefaciens")
|
| 637 |
+
trans_dephospho_coa_rfl_balance[...] = trans_dephospho_coa_rfl <= v_mgk['EX_cpd00655_e0']
|
| 638 |
+
|
| 639 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_rfl_balance = Equation(container=cowmunity, name='trans_cobinamide_rfl_balance', description="Balance for cobinamide transfer to R. flavefaciens")
|
| 640 |
+
# ****** commented to preserve MGK FLux ********* trans_cobinamide_rfl_balance[...] = trans_cobinamide_rfl <= v_mgk['EX_cpd03422_e0']
|
| 641 |
+
|
| 642 |
+
trans_alanine_rfl_balance = Equation(container=cowmunity, name='trans_alanine_rfl_balance', description="Balance for alanine transfer to R. flavefaciens")
|
| 643 |
+
trans_alanine_rfl_balance[...] = trans_alanine_rfl <= v_mgk['EX_cpd00035_e0']
|
| 644 |
+
|
| 645 |
+
trans_leucine_rfl_balance = Equation(container=cowmunity, name='trans_leucine_rfl_balance', description="Balance for leucine transfer to R. flavefaciens")
|
| 646 |
+
trans_leucine_rfl_balance[...] = trans_leucine_rfl <= v_mgk['EX_cpd00107_e0']
|
| 647 |
+
|
| 648 |
+
trans_glycine_rfl_balance = Equation(container=cowmunity, name='trans_glycine_rfl_balance', description="Balance for glycine transfer to R. flavefaciens")
|
| 649 |
+
trans_glycine_rfl_balance[...] = trans_glycine_rfl <= v_mgk['EX_cpd00033_e0']
|
| 650 |
+
|
| 651 |
+
# ****** commented to preserve RFL FLux ********* trans_proline_rfl_balance = Equation(container=cowmunity, name='trans_proline_rfl_balance', description="Balance for proline transfer to R. flavefaciens")
|
| 652 |
+
# ****** commented to preserve RFL FLux ********* trans_proline_rfl_balance[...] = trans_proline_rfl <= v_mgk['EX_cpd00129_e0']
|
| 653 |
+
|
| 654 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_rfl_balance = Equation(container=cowmunity, name='trans_aminoethanol_rfl_balance', description="Balance for aminoethanol transfer to R. flavefaciens")
|
| 655 |
+
# ****** commented to preserve MGK FLux ********* trans_aminoethanol_rfl_balance[...] = trans_aminoethanol_rfl <= v_mgk['EX_cpd00162_e0']
|
| 656 |
+
|
| 657 |
+
# ****** commented to preserve MGK FLux ********* overall_cobinamide_balance = Equation(container=cowmunity, name='overall_cobinamide_balance', description='Balance for cobinamide transfer for both prm and rfl')
|
| 658 |
+
# ****** commented to preserve MGK FLux ********* overall_cobinamide_balance[...] = trans_cobinamide_prm + trans_cobinamide_rfl <= v_mgk['EX_cpd03422_e0']
|
| 659 |
+
|
| 660 |
+
overall_alanine_balance = Equation(container=cowmunity, name='overall_alanine_balance', description='Balance for alanine transfer for both prm and rfl')
|
| 661 |
+
overall_alanine_balance[...] = trans_alanine_prm + trans_alanine_rfl <= v_mgk['EX_cpd00035_e0']
|
| 662 |
+
|
| 663 |
+
overall_leucine_balance = Equation(container=cowmunity, name='overall_leucine_balance', description='Balance for leucine transfer for both prm and rfl')
|
| 664 |
+
overall_leucine_balance[...] = trans_leucine_prm + trans_leucine_rfl <= v_mgk['EX_cpd00107_e0']
|
| 665 |
+
|
| 666 |
+
overall_glycine_balance = Equation(container=cowmunity, name='overall_glycine_balance', description='Balance for glycine transfer for both prm and rfl')
|
| 667 |
+
overall_glycine_balance[...] = trans_glycine_prm + trans_glycine_rfl <= v_mgk['EX_cpd00033_e0']
|
| 668 |
+
|
| 669 |
+
overall_proline_balance = Equation(container=cowmunity, name='overall_proline_balance', description='Balance for proline transfer for both prm and rfl')
|
| 670 |
+
overall_proline_balance[...] = trans_proline_prm + trans_proline_rfl <= v_mgk['EX_cpd00129_e0']
|
| 671 |
+
|
| 672 |
+
# ****** commented to preserve MGK FLux ********* overall_aminoethanol_balance = Equation(container=cowmunity, name='overall_aminoethanol_balance', description='Balance for aminoethanol transfer for both prm and rfl')
|
| 673 |
+
# ****** commented to preserve MGK FLux ********* overall_aminoethanol_balance[...] = trans_aminoethanol_prm + trans_aminoethanol_rfl <= v_mgk['EX_cpd00162_e0']
|
| 674 |
+
|
| 675 |
+
# adding the constraints to each model
|
| 676 |
+
|
| 677 |
+
constraint_CO2_mgk = Equation(container=cowmunity, name="constraint_CO2_mgk", description="constraint for the uptake of CO2 to M. Gottschalkii")
|
| 678 |
+
constraint_CO2_mgk[...] = trans_CO2_mgk == v_mgk['EX_cpd00011_e0']
|
| 679 |
+
|
| 680 |
+
constraint_H2_mgk = Equation(container=cowmunity, name="constraint_H2_mgk", description="constraint for the uptake of H2 to M. Gottschalkii")
|
| 681 |
+
constraint_H2_mgk[...] = trans_H2_mgk == v_mgk['EX_cpd11640_e0']
|
| 682 |
+
|
| 683 |
+
constraint_formate_mgk = Equation(container=cowmunity, name='constraint_formate_mgk', description="constraint for the uptake of formate to M. Gottschalkii")
|
| 684 |
+
constraint_formate_mgk[...] = trans_formate_mgk == v_mgk['EX_cpd00047_e0']
|
| 685 |
+
|
| 686 |
+
constraint_acetate_mgk = Equation(container=cowmunity, name="constraint_acetate_mgk", description="constraint for the uptake of acetate to M. Gottschalkii")
|
| 687 |
+
constraint_acetate_mgk[...] = trans_acetate_mgk == v_mgk['EX_cpd00029_e0']
|
| 688 |
+
|
| 689 |
+
constraint_d_mannose_mgk = Equation(container=cowmunity, name="constraint_dmannose_mgk", description="constraint for the uptake of D-mannose to M. Gottschalkii")
|
| 690 |
+
constraint_d_mannose_mgk[...] = trans_d_mannose_mgk == v_mgk['EX_cpd00138_e0']
|
| 691 |
+
|
| 692 |
+
constraint_d_fructose_mgk = Equation(container=cowmunity, name="constraint_dfructose_mgk", description="constraint for the uptake of D-fructose to M. Gottschalkii")
|
| 693 |
+
constraint_d_fructose_mgk[...] = trans_d_fructose_mgk == v_mgk['EX_cpd00082_e0']
|
| 694 |
+
|
| 695 |
+
constraint_tetrathionate_mgk = Equation(container=cowmunity, name="constraint_tetrathionate_mgk", description="constraint for the uptake of tetrathionate to M. Gottschalkii")
|
| 696 |
+
constraint_tetrathionate_mgk[...] = trans_tetrathionate_mgk == v_mgk['EX_cpd01414_e0']
|
| 697 |
+
|
| 698 |
+
constraint_thiosulfate_mgk = Equation(container=cowmunity, name="constraint_thiosulfate_mgk", description="constraint for the uptake of thiosulfate to M. Gottschalkii")
|
| 699 |
+
constraint_thiosulfate_mgk[...] = trans_thiosulfate_mgk == v_mgk['EX_cpd00268_e0']
|
| 700 |
+
|
| 701 |
+
constraint_cellulose_prm = Equation(container=cowmunity, name='constraint_cellulose_prm', description="constraint for the uptake of cellulose to P. ruminicola")
|
| 702 |
+
constraint_cellulose_prm[...] = trans_cellulose_prm == v_prm['EX_cpd11746_e0']
|
| 703 |
+
|
| 704 |
+
constraint_d_glucose_prm = Equation(container=cowmunity, name='constraint_d_glucose_prm', description="constraint for the uptake of D-Glucose to P. ruminicola")
|
| 705 |
+
constraint_d_glucose_prm[...] = trans_d_glucose_prm == v_prm['EX_cpd00027_e0']
|
| 706 |
+
|
| 707 |
+
constraint_acetate_prm = Equation(container=cowmunity, name='constraint_acetate_prm', description="constraint for the uptake of Acetate to P. ruminicola")
|
| 708 |
+
constraint_acetate_prm[...] = trans_acetate_prm == v_prm['EX_cpd00029_e0']
|
| 709 |
+
|
| 710 |
+
constraint_l_arabinose_prm = Equation(container=cowmunity, name='constraint_l_arabinose_prm', description="constraint for the uptake of L-Arabinose to P. ruminicola")
|
| 711 |
+
constraint_l_arabinose_prm[...] = trans_l_arabinose_prm == v_prm['EX_cpd00224_e0']
|
| 712 |
+
|
| 713 |
+
constraint_biotin_prm = Equation(container=cowmunity, name='constraint_biotin_prm', description="constraint for the uptake of Biotin to P. ruminicola")
|
| 714 |
+
constraint_biotin_prm[...] = trans_biotin_prm == v_prm['EX_cpd00104_e0']
|
| 715 |
+
|
| 716 |
+
# ****** commented to preserve RFL FLux ********* constraint_thiamin_prm = Equation(container=cowmunity, name='constraint_thiamin_prm', description="constraint for the uptake of Thiamin to P. ruminicola")
|
| 717 |
+
# ****** commented to preserve RFL FLux ********* constraint_thiamin_prm[...] = trans_thiamin_prm == v_prm['EX_cpd00305_e0']
|
| 718 |
+
|
| 719 |
+
constraint_octadecenoate_prm = Equation(container=cowmunity, name='constraint_octadecenoate_prm', description="constraint for the uptake of octadecenoate to P. ruminicola")
|
| 720 |
+
constraint_octadecenoate_prm[...] = trans_octadecenoate_prm == v_prm['EX_cpd15269_e0']
|
| 721 |
+
|
| 722 |
+
constraint_maltoheptaose_prm = Equation(container=cowmunity, name='constraint_maltoheptaose_prm', description="constraint for the uptake of Maltoheptaose to P. ruminicola")
|
| 723 |
+
constraint_maltoheptaose_prm[...] = trans_maltoheptaose_prm == v_prm['EX_cpd15494_e0']
|
| 724 |
+
|
| 725 |
+
constraint_nitrite_prm = Equation(container=cowmunity, name='constraint_nitrite_prm', description="constraint for the uptake of Nitrite to P. ruminicola")
|
| 726 |
+
constraint_nitrite_prm[...] = trans_nitrite_prm == v_prm['EX_cpd00075_e0']
|
| 727 |
+
|
| 728 |
+
# ****** commented to preserve MGK FLux ********* constraint_n_acetyl_d_glucosamine_prm = Equation(container=cowmunity, name='constraint_n_acetyl_d_glucosamine_prm', description="constraint for the uptake of N-Acetyl-D-glucosamine to P. ruminicola")
|
| 729 |
+
# ****** commented to preserve MGK FLux ********* constraint_n_acetyl_d_glucosamine_prm[...] = trans_n_acetyl_d_glucosamine_prm == v_prm['EX_cpd00122_e0']
|
| 730 |
+
|
| 731 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_prm = Equation(container=cowmunity, name='constraint_aminoethanol_prm', description="constraint for the uptake of Aminoethanol to P. ruminicola")
|
| 732 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_prm[...] = trans_aminoethanol_prm == v_prm['EX_cpd00162_e0']
|
| 733 |
+
|
| 734 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_prm = Equation(container=cowmunity, name='constraint_cobinamide_prm', description="constraint for the uptake of Cobinamide to P. ruminicola")
|
| 735 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_prm[...] = trans_cobinamide_prm == v_prm['EX_cpd03422_e0']
|
| 736 |
+
|
| 737 |
+
constraint_alanine_prm = Equation(container=cowmunity, name='constraint_alanine_prm', description="constraint for the uptake of Alanine to P. ruminicola")
|
| 738 |
+
constraint_alanine_prm[...] = trans_alanine_prm == v_prm['EX_cpd00035_e0']
|
| 739 |
+
|
| 740 |
+
constraint_leucine_prm = Equation(container=cowmunity, name='constraint_leucine_prm', description="constraint for the uptake of Leucine to P. ruminicola")
|
| 741 |
+
constraint_leucine_prm[...] = trans_leucine_prm == v_prm['EX_cpd00107_e0']
|
| 742 |
+
|
| 743 |
+
constraint_glycine_prm = Equation(container=cowmunity, name='constraint_glycine_prm', description="constraint for the uptake of Glycine to P. ruminicola")
|
| 744 |
+
constraint_glycine_prm[...] = trans_glycine_prm == v_prm['EX_cpd00033_e0']
|
| 745 |
+
|
| 746 |
+
constraint_proline_prm = Equation(container=cowmunity, name='constraint_proline_prm', description="constraint for the uptake of Proline to P. ruminicola")
|
| 747 |
+
constraint_proline_prm[...] = trans_proline_prm == v_prm['EX_cpd00129_e0']
|
| 748 |
+
|
| 749 |
+
constraint_d_galacturonate_rfl = Equation(container=cowmunity, name='constraint_d_galacturonate_rfl', description="constraint for the uptake of D-Galacturonate to R. flavefaciens")
|
| 750 |
+
constraint_d_galacturonate_rfl[...] = trans_d_galacturonate_rfl == v_rfl['EX_cpd00280_e0']
|
| 751 |
+
|
| 752 |
+
constraint_deoxyadenosine_rfl = Equation(container=cowmunity, name='constraint_deoxyadenosine_rfl', description="constraint for the uptake of Deoxyadenosine to R. flavefaciens")
|
| 753 |
+
constraint_deoxyadenosine_rfl[...] = trans_deoxyadenosine_rfl == v_rfl['EX_cpd00438_e0']
|
| 754 |
+
|
| 755 |
+
constraint_dephospho_coa_rfl = Equation(container=cowmunity, name='constraint_dephospho_coa_rfl', description="constraint for the uptake of Dephospho-CoA to R. flavefaciens")
|
| 756 |
+
constraint_dephospho_coa_rfl[...] = trans_dephospho_coa_rfl == v_rfl['EX_cpd00655_e0']
|
| 757 |
+
|
| 758 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_rfl = Equation(container=cowmunity, name='constraint_cobinamide_rfl', description="constraint for the uptake of Cobinamide to R. flavefaciens")
|
| 759 |
+
# ****** commented to preserve MGK FLux ********* constraint_cobinamide_rfl[...] = trans_cobinamide_rfl == v_rfl['EX_cpd03422_e0']
|
| 760 |
+
|
| 761 |
+
constraint_alanine_rfl = Equation(container=cowmunity, name='constraint_alanine_rfl', description="constraint for the uptake of Alanine to R. flavefaciens")
|
| 762 |
+
constraint_alanine_rfl[...] = trans_alanine_rfl == v_rfl['EX_cpd00035_e0']
|
| 763 |
+
|
| 764 |
+
constraint_leucine_rfl = Equation(container=cowmunity, name='constraint_leucine_rfl', description="constraint for the uptake of Leucine to R. flavefaciens")
|
| 765 |
+
constraint_leucine_rfl[...] = trans_leucine_rfl == v_rfl['EX_cpd00107_e0']
|
| 766 |
+
|
| 767 |
+
constraint_glycine_rfl = Equation(container=cowmunity, name='constraint_glycine_rfl', description="constraint for the uptake of Glycine to R. flavefaciens")
|
| 768 |
+
constraint_glycine_rfl[...] = trans_glycine_rfl == v_rfl['EX_cpd00033_e0']
|
| 769 |
+
|
| 770 |
+
# ****** commented to preserve RFL FLux ********* constraint_proline_rfl = Equation(container=cowmunity, name='constraint_proline_rfl', description="constraint for the uptake of Proline to R. flavefaciens")
|
| 771 |
+
# ****** commented to preserve RFL FLux ********* constraint_proline_rfl[...] = trans_proline_rfl == v_rfl['EX_cpd00129_e0']
|
| 772 |
+
|
| 773 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_rfl = Equation(container=cowmunity, name='constraint_aminoethanol_rfl', description="constraint for the uptake of Aminoethanol to R. flavefaciens")
|
| 774 |
+
# ****** commented to preserve MGK FLux ********* constraint_aminoethanol_rfl[...] = trans_aminoethanol_rfl == v_rfl['EX_cpd00162_e0']
|
| 775 |
+
|
| 776 |
+
# mass balance equations
|
| 777 |
+
|
| 778 |
+
mgk_mass_balance = Equation(container=cowmunity, name='mgk_mass_balance', domain=i_mgk, description='overall mass balance for mgk')
|
| 779 |
+
mgk_mass_balance[i_mgk] = Sum(j_mgk, S_mgk[j_mgk, i_mgk] * v_mgk[j_mgk]) == 0
|
| 780 |
+
|
| 781 |
+
prm_mass_balance = Equation(container=cowmunity, name='prm_mass_balance', domain=i_prm, description='overall mass balance for prm')
|
| 782 |
+
prm_mass_balance[i_prm] = Sum(j_prm, S_prm[j_prm, i_prm] * v_prm[j_prm]) == 0
|
| 783 |
+
|
| 784 |
+
rfl_mass_balance = Equation(container=cowmunity, name='rfl_mass_balance', domain=i_rfl, description='overall mass balance for rfl')
|
| 785 |
+
rfl_mass_balance[i_rfl] = Sum(j_rfl, S_rfl[j_rfl, i_rfl] * v_rfl[j_rfl]) == 0
|
| 786 |
+
|
| 787 |
+
# dual problem constraint equations
|
| 788 |
+
|
| 789 |
+
mgk_dual_constraint = Equation(container=cowmunity, name="mgk_dual_constraint", domain=j_mgk, description="Dual constraint for MGK")
|
| 790 |
+
mgk_dual_constraint[j_mgk] = Sum(i_mgk, lambda_mgk[i_mgk] * S_mgk[j_mgk, i_mgk]) + \
|
| 791 |
+
muUB_mgk[j_mgk] - muLB_mgk[j_mgk] == 0
|
| 792 |
+
|
| 793 |
+
prm_dual_constraint = Equation(container=cowmunity, name="prm_dual_constraint", domain=j_prm, description="Dual constraint for PRM")
|
| 794 |
+
prm_dual_constraint[j_prm] = Sum(i_prm, lambda_prm[i_prm] * S_prm[j_prm, i_prm]) + \
|
| 795 |
+
muUB_prm[j_prm] - muLB_prm[j_prm] == 0
|
| 796 |
+
|
| 797 |
+
rfl_dual_constraint = Equation(container=cowmunity, name="rfl_dual_constraint", domain=j_rfl, description="Dual constraint for RFL")
|
| 798 |
+
rfl_dual_constraint[j_rfl] = Sum(i_rfl, lambda_rfl[i_rfl] * S_rfl[j_rfl, i_rfl]) + \
|
| 799 |
+
muUB_rfl[j_rfl] - muLB_rfl[j_rfl] == 0
|
| 800 |
+
|
| 801 |
+
def FixSBMLs():
|
| 802 |
+
print("Fixing SBML files...")
|
| 803 |
+
|
| 804 |
+
def add_reaction(file_name, metabolite_code, metabolite_name, charge=0):
|
| 805 |
+
# Define the SBML document and model
|
| 806 |
+
reader = libsbml.SBMLReader()
|
| 807 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 808 |
+
model = document.getModel()
|
| 809 |
+
|
| 810 |
+
# Check if the cytosol species already exists
|
| 811 |
+
species_id = f'M_{metabolite_code}_c0'
|
| 812 |
+
if model.getSpecies(species_id) is None:
|
| 813 |
+
species = model.createSpecies()
|
| 814 |
+
species.setId(species_id)
|
| 815 |
+
species.setCompartment('c0')
|
| 816 |
+
species.setName(f'{metabolite_name}[c0]')
|
| 817 |
+
species.setCharge(charge)
|
| 818 |
+
species.setBoundaryCondition(False)
|
| 819 |
+
|
| 820 |
+
cytosol_species = model.getSpecies(species_id)
|
| 821 |
+
|
| 822 |
+
# create the extracellular species
|
| 823 |
+
species = model.createSpecies()
|
| 824 |
+
species.setId(f'M_{metabolite_code}_e0')
|
| 825 |
+
species.setCompartment('e0')
|
| 826 |
+
species.setName(f'{metabolite_name}[e0]')
|
| 827 |
+
species.setCharge(int(cytosol_species.getCharge()))
|
| 828 |
+
species.setBoundaryCondition(False)
|
| 829 |
+
|
| 830 |
+
|
| 831 |
+
# Create the export/import reaction
|
| 832 |
+
reaction = model.createReaction()
|
| 833 |
+
reaction.setId(f'EX_{metabolite_code}_e0')
|
| 834 |
+
reaction.setName(f'{metabolite_name} export/import')
|
| 835 |
+
reaction.setReversible(True) # Set reversibility
|
| 836 |
+
|
| 837 |
+
# Add reactant to the reaction
|
| 838 |
+
reactant1 = reaction.createReactant()
|
| 839 |
+
reactant1.setSpecies(f'M_{metabolite_code}_e0') # Use the species ID created above
|
| 840 |
+
reactant1.setStoichiometry(1)
|
| 841 |
+
reactant1.setConstant(False)
|
| 842 |
+
|
| 843 |
+
# 6. Define the kinetic law (e.g., Mass Action kinetics: k * S1)
|
| 844 |
+
kinetic_law = reaction.createKineticLaw()
|
| 845 |
+
# Create a parameter for the rate constant
|
| 846 |
+
lb = kinetic_law.createParameter()
|
| 847 |
+
lb.setId('LOWER_BOUND')
|
| 848 |
+
lb.setValue(-1000)
|
| 849 |
+
lb.setName('mmol_per_gDW_per_hr')
|
| 850 |
+
ub = kinetic_law.createParameter()
|
| 851 |
+
ub.setId('UPPER_BOUND')
|
| 852 |
+
ub.setValue(1000)
|
| 853 |
+
ub.setName('mmol_per_gDW_per_hr')
|
| 854 |
+
obj = kinetic_law.createParameter()
|
| 855 |
+
obj.setId('OBJECTIVE_COEFFICIENT')
|
| 856 |
+
obj.setValue(0)
|
| 857 |
+
flx = kinetic_law.createParameter()
|
| 858 |
+
flx.setId('FLUX_VALUE')
|
| 859 |
+
flx.setValue(0)
|
| 860 |
+
flx.setName('mmol_per_gDW_per_hr')
|
| 861 |
+
|
| 862 |
+
|
| 863 |
+
# Set the math for the kinetic law using MathML
|
| 864 |
+
# You can use libsbml.parseL3Formula to convert from infix string to MathML AST
|
| 865 |
+
math_ml_string = (
|
| 866 |
+
'<math xmlns="http://www.w3.org/1998/Math/MathML">'
|
| 867 |
+
'<ci> FLUX_VALUE </ci>'
|
| 868 |
+
'</math>'
|
| 869 |
+
)
|
| 870 |
+
math_ast = libsbml.readMathMLFromString(math_ml_string)
|
| 871 |
+
if math_ast:
|
| 872 |
+
kinetic_law.setMath(math_ast)
|
| 873 |
+
else:
|
| 874 |
+
print("Error: Could not parse MathML string.")
|
| 875 |
+
|
| 876 |
+
# create the reaction to convert from extracellular to cytosol
|
| 877 |
+
transport_reaction = model.createReaction()
|
| 878 |
+
transport_reaction.setId(f'R_{metabolite_code}_transport')
|
| 879 |
+
transport_reaction.setName(f'{metabolite_name} transport')
|
| 880 |
+
transport_reaction.setReversible(True) # Set reversibility
|
| 881 |
+
|
| 882 |
+
# Add reactant to the reaction
|
| 883 |
+
cytosol = transport_reaction.createReactant()
|
| 884 |
+
cytosol.setSpecies(f'M_{metabolite_code}_c0') # Use the species ID created above
|
| 885 |
+
cytosol.setStoichiometry(1)
|
| 886 |
+
cytosol.setConstant(False)
|
| 887 |
+
|
| 888 |
+
# Add product to the reaction
|
| 889 |
+
extracellular = transport_reaction.createProduct()
|
| 890 |
+
extracellular.setSpecies(f'M_{metabolite_code}_e0') # Use the species ID created above
|
| 891 |
+
extracellular.setStoichiometry(1)
|
| 892 |
+
extracellular.setConstant(False)
|
| 893 |
+
|
| 894 |
+
# 6. Define the kinetic law (e.g., Mass Action kinetics: k * S1)
|
| 895 |
+
kinetic_law = transport_reaction.createKineticLaw()
|
| 896 |
+
# Create a parameter for the rate constant
|
| 897 |
+
lb = kinetic_law.createParameter()
|
| 898 |
+
lb.setId('LOWER_BOUND')
|
| 899 |
+
lb.setValue(-1000)
|
| 900 |
+
lb.setName('mmol_per_gDW_per_hr')
|
| 901 |
+
ub = kinetic_law.createParameter()
|
| 902 |
+
ub.setId('UPPER_BOUND')
|
| 903 |
+
ub.setValue(1000)
|
| 904 |
+
ub.setName('mmol_per_gDW_per_hr')
|
| 905 |
+
obj = kinetic_law.createParameter()
|
| 906 |
+
obj.setId('OBJECTIVE_COEFFICIENT')
|
| 907 |
+
obj.setValue(0)
|
| 908 |
+
flx = kinetic_law.createParameter()
|
| 909 |
+
flx.setId('FLUX_VALUE')
|
| 910 |
+
flx.setValue(0)
|
| 911 |
+
flx.setName('mmol_per_gDW_per_hr')
|
| 912 |
+
|
| 913 |
+
|
| 914 |
+
# Set the math for the kinetic law using MathML
|
| 915 |
+
# You can use libsbml.parseL3Formula to convert from infix string to MathML AST
|
| 916 |
+
math_ml_string = (
|
| 917 |
+
'<math xmlns="http://www.w3.org/1998/Math/MathML">'
|
| 918 |
+
'<ci> FLUX_VALUE </ci>'
|
| 919 |
+
'</math>'
|
| 920 |
+
)
|
| 921 |
+
math_ast = libsbml.readMathMLFromString(math_ml_string)
|
| 922 |
+
if math_ast:
|
| 923 |
+
kinetic_law.setMath(math_ast)
|
| 924 |
+
else:
|
| 925 |
+
print("Error: Could not parse MathML string.")
|
| 926 |
+
|
| 927 |
+
libsbml.writeSBMLToFile(document, f'model files/{file_name}')
|
| 928 |
+
|
| 929 |
+
|
| 930 |
+
def add_version(file_name, version):
|
| 931 |
+
# Define the SBML document and model
|
| 932 |
+
reader = libsbml.SBMLReader()
|
| 933 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 934 |
+
model = document.getModel()
|
| 935 |
+
|
| 936 |
+
# Set the version in the model's annotation
|
| 937 |
+
model.setNotes(version)
|
| 938 |
+
|
| 939 |
+
# Write the updated SBML document back to file
|
| 940 |
+
libsbml.writeSBMLToFile(document, f'model files/{file_name}')
|
| 941 |
+
|
| 942 |
+
def check_version(file_name, version):
|
| 943 |
+
# Define the SBML document and model
|
| 944 |
+
reader = libsbml.SBMLReader()
|
| 945 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 946 |
+
model = document.getModel()
|
| 947 |
+
|
| 948 |
+
# Check if the version matches
|
| 949 |
+
notes = model.getNotesString()
|
| 950 |
+
return notes == f'<notes>{version}</notes>'
|
| 951 |
+
|
| 952 |
+
version = 'v2.5'
|
| 953 |
+
|
| 954 |
+
if check_version('M. gottschalkii.xml', version) is False:
|
| 955 |
+
print('M. gottschalkii.xml is not up to date, updating...')
|
| 956 |
+
add_reaction('M. gottschalkii.xml', 'cpd00035', 'L-Alanine')
|
| 957 |
+
add_reaction('M. gottschalkii.xml', 'cpd00107', 'L-Leucine')
|
| 958 |
+
add_reaction('M. gottschalkii.xml', 'cpd00033', 'Glycine')
|
| 959 |
+
add_version('M. gottschalkii.xml', version)
|
| 960 |
+
|
| 961 |
+
if check_version('P. ruminicola.xml', version) is False:
|
| 962 |
+
print('P. ruminicola.xml is not up to date, updating...')
|
| 963 |
+
add_reaction('P. ruminicola.xml', 'cpd00035', 'L-Alanine')
|
| 964 |
+
add_reaction('P. ruminicola.xml', 'cpd00107', 'L-Leucine')
|
| 965 |
+
add_reaction('P. ruminicola.xml', 'cpd00033', 'Glycine')
|
| 966 |
+
add_reaction('P. ruminicola.xml', 'cpd11657', 'Starch')
|
| 967 |
+
add_reaction('P. ruminicola.xml', 'cpd00076', 'Sucrose')
|
| 968 |
+
add_reaction('P. ruminicola.xml', 'cpd00053', 'L-Glutamine')
|
| 969 |
+
add_reaction('P. ruminicola.xml', 'cpd00161', 'L-Threonine')
|
| 970 |
+
add_reaction('P. ruminicola.xml', 'cpd00348', 'D-Galactose 1-phosphate')
|
| 971 |
+
add_reaction('P. ruminicola.xml', 'cpd00084', 'L-Cysteine')
|
| 972 |
+
add_reaction('P. ruminicola.xml', 'cpd00052', 'CTP')
|
| 973 |
+
add_reaction('P. ruminicola.xml', 'cpd00002', 'ATP')
|
| 974 |
+
add_reaction('P. ruminicola.xml', 'cpd00062', 'UTP')
|
| 975 |
+
add_reaction('P. ruminicola.xml', 'cpd00356', 'dCTP')
|
| 976 |
+
add_reaction('P. ruminicola.xml', 'cpd00073', 'Urea')
|
| 977 |
+
add_version('P. ruminicola.xml', version)
|
| 978 |
+
|
| 979 |
+
if check_version('R. flavefaciens.xml', version) is False:
|
| 980 |
+
print('R. flavefaciens.xml is not up to date, updating...')
|
| 981 |
+
add_reaction('R. flavefaciens.xml', 'cpd00035', 'L-Alanine')
|
| 982 |
+
add_reaction('R. flavefaciens.xml', 'cpd00033', 'Glycine')
|
| 983 |
+
add_reaction('R. flavefaciens.xml', 'cpd00053', 'L-Glutamine')
|
| 984 |
+
add_reaction('R. flavefaciens.xml', 'cpd00161', 'L-Threonine')
|
| 985 |
+
add_reaction('R. flavefaciens.xml', 'cpd00348', 'D-Galactose 1-phosphate')
|
| 986 |
+
add_reaction('R. flavefaciens.xml', 'cpd00084', 'L-Cysteine')
|
| 987 |
+
add_reaction('R. flavefaciens.xml', 'cpd00052', 'CTP')
|
| 988 |
+
add_reaction('R. flavefaciens.xml', 'cpd00002', 'ATP')
|
| 989 |
+
add_reaction('R. flavefaciens.xml', 'cpd00062', 'UTP')
|
| 990 |
+
add_reaction('R. flavefaciens.xml', 'cpd00356', 'dCTP')
|
| 991 |
+
add_reaction('R. flavefaciens.xml', 'cpd00073', 'Urea')
|
| 992 |
+
add_version('R. flavefaciens.xml', version)
|
| 993 |
+
|
| 994 |
+
|
| 995 |
+
def remove_duplicate_species_and_reactions(file_name):
|
| 996 |
+
# Define the SBML document and model
|
| 997 |
+
reader = libsbml.SBMLReader()
|
| 998 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 999 |
+
model = document.getModel()
|
| 1000 |
+
|
| 1001 |
+
# --- Remove Duplicate Species ---
|
| 1002 |
+
seen_species = []
|
| 1003 |
+
species_to_remove = []
|
| 1004 |
+
|
| 1005 |
+
for i in range(model.getNumSpecies()):
|
| 1006 |
+
species = model.getSpecies(i)
|
| 1007 |
+
id = species.getId()
|
| 1008 |
+
|
| 1009 |
+
if id in seen_species:
|
| 1010 |
+
species_to_remove.append(species.getId())
|
| 1011 |
+
else:
|
| 1012 |
+
seen_species.append(species.getId())
|
| 1013 |
+
|
| 1014 |
+
# Remove species (iterate in reverse to avoid index issues)
|
| 1015 |
+
for item in reversed(species_to_remove):
|
| 1016 |
+
model.removeSpecies(item)
|
| 1017 |
+
|
| 1018 |
+
# --- Remove Duplicate Reactions ---
|
| 1019 |
+
seen_reactions = []
|
| 1020 |
+
reactions_to_remove = []
|
| 1021 |
+
|
| 1022 |
+
for i in range(model.getNumReactions()):
|
| 1023 |
+
reaction = model.getReaction(i)
|
| 1024 |
+
id = reaction.getId()
|
| 1025 |
+
|
| 1026 |
+
if id in seen_reactions:
|
| 1027 |
+
reactions_to_remove.append(reaction.getId())
|
| 1028 |
+
else:
|
| 1029 |
+
seen_reactions.append(reaction.getId())
|
| 1030 |
+
|
| 1031 |
+
# Remove reactions
|
| 1032 |
+
for reaction_id in reversed(reactions_to_remove):
|
| 1033 |
+
model.removeReaction(reaction_id)
|
| 1034 |
+
|
| 1035 |
+
# Save the modified model (optional)
|
| 1036 |
+
writer = libsbml.SBMLWriter()
|
| 1037 |
+
libsbml.writeSBMLToFile(document, f'model files/{file_name}')
|
| 1038 |
+
|
| 1039 |
+
remove_duplicate_species_and_reactions('M. gottschalkii.xml')
|
| 1040 |
+
remove_duplicate_species_and_reactions('P. ruminicola.xml')
|
| 1041 |
+
remove_duplicate_species_and_reactions('R. flavefaciens.xml')
|
| 1042 |
+
|
| 1043 |
+
# removing a duplicate product that slipped through the cracks
|
| 1044 |
+
|
| 1045 |
+
reader = libsbml.SBMLReader()
|
| 1046 |
+
document = reader.readSBML(f'model files/R. flavefaciens.xml')
|
| 1047 |
+
model = document.getModel()
|
| 1048 |
+
|
| 1049 |
+
reaction = model.getReaction('R_R01896_c0')
|
| 1050 |
+
reaction.removeProduct('M_cpd00067_c0')
|
| 1051 |
+
|
| 1052 |
+
writer = libsbml.SBMLWriter()
|
| 1053 |
+
libsbml.writeSBMLToFile(document, f'model files/R. flavefaciens.xml')
|
| 1054 |
+
|
| 1055 |
+
def solve(solver_name='IPOPT'):
|
| 1056 |
+
|
| 1057 |
+
|
| 1058 |
+
global model
|
| 1059 |
+
# Create model
|
| 1060 |
+
model = Model(container=cowmunity, name="COWMUNITY", equations=cowmunity.getEquations(),
|
| 1061 |
+
problem="NLP", sense=Sense.MAX, objective=objective_variable)
|
| 1062 |
+
|
| 1063 |
+
# Set solver options
|
| 1064 |
+
options = Options(nlp=solver_name, equation_listing_limit=10, variable_listing_limit=10, time_limit=20, threads=0)
|
| 1065 |
+
|
| 1066 |
+
# Solve the model
|
| 1067 |
+
print(f"Solving with {solver_name}...")
|
| 1068 |
+
model.solve(options=options)
|
| 1069 |
+
|
| 1070 |
+
# check solution status
|
| 1071 |
+
status = model.solve_status
|
| 1072 |
+
if status == SolveStatus.NormalCompletion:
|
| 1073 |
+
print("Optimal solution found!")
|
| 1074 |
+
else:
|
| 1075 |
+
print(f"Solver terminated with status: {status}")
|
| 1076 |
+
|
| 1077 |
+
def extract_results():
|
| 1078 |
+
"""Extract and store results"""
|
| 1079 |
+
global results
|
| 1080 |
+
results = {
|
| 1081 |
+
'objective_value': objective_variable.records['level'].iloc[0],
|
| 1082 |
+
'mgk_biomass': v_mgk.records.loc[v_mgk.records['j_mgk'] == 'R_biomass0', 'level'].iloc[0],
|
| 1083 |
+
'prm_biomass': v_prm.records.loc[v_prm.records['j_prm'] == 'R_biomass0', 'level'].iloc[0],
|
| 1084 |
+
'rfl_biomass': v_rfl.records.loc[v_rfl.records['j_rfl'] == 'R_biomass0', 'level'].iloc[0],
|
| 1085 |
+
'methane_flux' : v_mgk.records.loc[v_mgk.records['j_mgk'] == 'EX_cpd01024_e0', 'level'].iloc[0]
|
| 1086 |
+
}
|
| 1087 |
+
|
| 1088 |
+
def save_results(treatment, methane = 'variable'):
|
| 1089 |
+
"""Save results to a CSV file"""
|
| 1090 |
+
os.makedirs(f'results/{methane}_methane_{treatment}_treatment', exist_ok=True)
|
| 1091 |
+
v_mgk.records.to_csv(f'results/{methane}_methane_{treatment}_treatment/mgk_records.csv', index=False)
|
| 1092 |
+
v_prm.records.to_csv(f'results/{methane}_methane_{treatment}_treatment/prm_records.csv', index=False)
|
| 1093 |
+
v_rfl.records.to_csv(f'results/{methane}_methane_{treatment}_treatment/rfl_records.csv', index=False)
|
| 1094 |
+
print(f"Results saved to 'results/{methane}_methane_{treatment}_treatment'.")
|
| 1095 |
+
|
| 1096 |
+
def print_results():
|
| 1097 |
+
"""Print results in a formatted way"""
|
| 1098 |
+
print()
|
| 1099 |
+
print("********************* RESULTS *********************")
|
| 1100 |
+
print(f"Total Biomass = {results['objective_value']:5f}")
|
| 1101 |
+
print()
|
| 1102 |
+
|
| 1103 |
+
print("********************* MGK *************************")
|
| 1104 |
+
print(f"MGK Biomass Flux = {results['mgk_biomass']:5f}")
|
| 1105 |
+
print(f"Methane Emission Flux = {results['methane_flux']:5f}")
|
| 1106 |
+
print()
|
| 1107 |
+
|
| 1108 |
+
print("********************* PRM *************************")
|
| 1109 |
+
print(f"PRM Biomass Flux = {results['prm_biomass']:5f}")
|
| 1110 |
+
print()
|
| 1111 |
+
|
| 1112 |
+
print("********************* RFL *************************")
|
| 1113 |
+
print(f"RFL Biomass Flux = {results['rfl_biomass']:5f}")
|
| 1114 |
+
print()
|
| 1115 |
+
|
| 1116 |
+
def bug_huntin():
|
| 1117 |
+
# This function is for debugging purposes, to check the model and variable records
|
| 1118 |
+
|
| 1119 |
+
def print_reaction(reaction):
|
| 1120 |
+
def check_reaction(reaction, file_name):
|
| 1121 |
+
reader = libsbml.SBMLReader()
|
| 1122 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1123 |
+
model = document.getModel()
|
| 1124 |
+
|
| 1125 |
+
reaction = model.getReaction(reaction)
|
| 1126 |
+
|
| 1127 |
+
if reaction is None:
|
| 1128 |
+
return None
|
| 1129 |
+
else:
|
| 1130 |
+
return reaction.getId()
|
| 1131 |
+
|
| 1132 |
+
if check_reaction(reaction, 'M. gottschalkii.xml') is None:
|
| 1133 |
+
print(f'Reaction {reaction} not found in M. gottschalkii model.')
|
| 1134 |
+
else:
|
| 1135 |
+
mgk_flux = v_mgk.records.loc[v_mgk.records['j_mgk'] == reaction.strip(), 'level'].iloc[0]
|
| 1136 |
+
print(f'MGK {reaction}: {mgk_flux}')
|
| 1137 |
+
if check_reaction(reaction, 'P. ruminicola.xml') is None:
|
| 1138 |
+
print(f'Reaction {reaction} not found in P. ruminicola model.')
|
| 1139 |
+
else:
|
| 1140 |
+
prm_flux = v_prm.records.loc[v_prm.records['j_prm'] == reaction.strip(), 'level'].iloc[0]
|
| 1141 |
+
print(f'PRM {reaction}: {prm_flux}')
|
| 1142 |
+
if check_reaction(reaction, 'R. flavefaciens.xml') is None:
|
| 1143 |
+
print(f'Reaction {reaction} not found in R. flavefaciens model.')
|
| 1144 |
+
else:
|
| 1145 |
+
rfl_flux = v_rfl.records.loc[v_rfl.records['j_rfl'] == reaction.strip(), 'level'].iloc[0]
|
| 1146 |
+
print(f'RFL {reaction}: {rfl_flux}')
|
| 1147 |
+
|
| 1148 |
+
|
| 1149 |
+
print_reaction('EX_cpd01188_e0')
|
| 1150 |
+
|
| 1151 |
+
|
| 1152 |
+
|
| 1153 |
+
def flux_investigation(file_name, v_set, j_set, i_set, metabolite):
|
| 1154 |
+
|
| 1155 |
+
reader = libsbml.SBMLReader()
|
| 1156 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1157 |
+
model = document.getModel()
|
| 1158 |
+
|
| 1159 |
+
relevant_reactions = []
|
| 1160 |
+
for i in range(model.getNumReactions()):
|
| 1161 |
+
reaction = model.getReaction(i)
|
| 1162 |
+
product = reaction.getProduct(metabolite)
|
| 1163 |
+
if product is None:
|
| 1164 |
+
continue
|
| 1165 |
+
else:
|
| 1166 |
+
relevant_reactions.append(reaction.id)
|
| 1167 |
+
|
| 1168 |
+
# species = model.getSpecies(metabolite)
|
| 1169 |
+
name = i_set.records.loc[i_set.records['index'] == metabolite, 'element_text'].iloc[0]
|
| 1170 |
+
print(file_name)
|
| 1171 |
+
print(f'\n*** {name} FLUXES ***')
|
| 1172 |
+
for item in relevant_reactions:
|
| 1173 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1174 |
+
print(f'{item} : {flux}')
|
| 1175 |
+
|
| 1176 |
+
print()
|
| 1177 |
+
|
| 1178 |
+
metabolite = 'M_cpd00033_c0'
|
| 1179 |
+
mgk = ('M. gottschalkii.xml', v_mgk, 'j_mgk', i_mgk)
|
| 1180 |
+
prm = ('P. ruminicola.xml', v_prm, 'j_prm', i_prm)
|
| 1181 |
+
rfl = ('R. flavefaciens.xml', v_rfl, 'j_rfl', i_rfl)
|
| 1182 |
+
|
| 1183 |
+
# flux_investigation(*mgk, metabolite)
|
| 1184 |
+
|
| 1185 |
+
def biomass_fluxes(file_name, v_set, j_set, i_set):
|
| 1186 |
+
list_to_investigate = []
|
| 1187 |
+
print()
|
| 1188 |
+
print('*'*10, file_name, '*'*10)
|
| 1189 |
+
|
| 1190 |
+
reader = libsbml.SBMLReader()
|
| 1191 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1192 |
+
model = document.getModel()
|
| 1193 |
+
|
| 1194 |
+
biomass_reactants = []
|
| 1195 |
+
biomass_reaction = model.getReaction('R_biomass0')
|
| 1196 |
+
for i in range(biomass_reaction.getNumReactants()):
|
| 1197 |
+
reactant = biomass_reaction.getReactant(i)
|
| 1198 |
+
biomass_reactants.append(reactant.getSpecies())
|
| 1199 |
+
|
| 1200 |
+
precursor_reactions = {}
|
| 1201 |
+
for item in biomass_reactants:
|
| 1202 |
+
relevant_reactions = []
|
| 1203 |
+
for i in range(model.getNumReactions()):
|
| 1204 |
+
reaction = model.getReaction(i)
|
| 1205 |
+
product = reaction.getProduct(f'{item}')
|
| 1206 |
+
if product is None:
|
| 1207 |
+
continue
|
| 1208 |
+
else:
|
| 1209 |
+
relevant_reactions.append(reaction.id)
|
| 1210 |
+
new_entry = {item : relevant_reactions}
|
| 1211 |
+
precursor_reactions.update(new_entry)
|
| 1212 |
+
|
| 1213 |
+
for key in precursor_reactions:
|
| 1214 |
+
flux_set = []
|
| 1215 |
+
relevant_reactions = precursor_reactions[key]
|
| 1216 |
+
species = biomass_reaction.getReactant(f'{key}').getSpecies()
|
| 1217 |
+
name = i_set.records.loc[i_set.records['index'] == species, 'element_text'].iloc[0]
|
| 1218 |
+
print(f'\n{name} FLUXES')
|
| 1219 |
+
for item in relevant_reactions:
|
| 1220 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1221 |
+
print(f'{item} : {flux}')
|
| 1222 |
+
flux_set.append(flux)
|
| 1223 |
+
print(f'Total flux for {name} = {sum(flux_set)}')
|
| 1224 |
+
if sum(flux_set) <= 1e-5:
|
| 1225 |
+
list_to_investigate.append(name)
|
| 1226 |
+
|
| 1227 |
+
print(f'\nBiomass precursors with zero or negative production:')
|
| 1228 |
+
for item in list_to_investigate:
|
| 1229 |
+
print(item)
|
| 1230 |
+
|
| 1231 |
+
print(model.getNumReactions(), 'reactions in the model')
|
| 1232 |
+
print(model.getNumSpecies(), 'species in the model')
|
| 1233 |
+
|
| 1234 |
+
# biomass_fluxes(*mgk)
|
| 1235 |
+
# biomass_fluxes(*prm)
|
| 1236 |
+
# biomass_fluxes(*rfl)
|
| 1237 |
+
|
| 1238 |
+
def zero_flux_reactions(file_name, v_set, j_set, i_set):
|
| 1239 |
+
reader = libsbml.SBMLReader()
|
| 1240 |
+
document = reader.readSBML(f'model files/{file_name}')
|
| 1241 |
+
model = document.getModel()
|
| 1242 |
+
|
| 1243 |
+
"""Return a list of reaction IDs in v_set where the flux is exactly zero."""
|
| 1244 |
+
zero_flux_df = v_set.records.loc[v_set.records['level'] == 0]
|
| 1245 |
+
zero_flux_list = zero_flux_df[j_set].tolist()
|
| 1246 |
+
|
| 1247 |
+
print(f'\n*** {file_name} REACTIONS WITH ZERO FLUX ***')
|
| 1248 |
+
for item in zero_flux_list:
|
| 1249 |
+
precursor_reactions = {}
|
| 1250 |
+
needy_dict = {}
|
| 1251 |
+
unmade_products = []
|
| 1252 |
+
zero_reaction = model.getReaction(item)
|
| 1253 |
+
for i in range(zero_reaction.getNumProducts()):
|
| 1254 |
+
product = zero_reaction.getProduct(i)
|
| 1255 |
+
unmade_products.append(product.getSpecies())
|
| 1256 |
+
print(f'\n{item}')
|
| 1257 |
+
for item in unmade_products:
|
| 1258 |
+
relevant_reactions = []
|
| 1259 |
+
needy_reactions = []
|
| 1260 |
+
for i in range(model.getNumReactions()):
|
| 1261 |
+
reaction = model.getReaction(i)
|
| 1262 |
+
product = reaction.getProduct(f'{item}')
|
| 1263 |
+
if product is None:
|
| 1264 |
+
continue
|
| 1265 |
+
else:
|
| 1266 |
+
relevant_reactions.append(reaction.id)
|
| 1267 |
+
new_entry = {item : relevant_reactions}
|
| 1268 |
+
precursor_reactions.update(new_entry)
|
| 1269 |
+
|
| 1270 |
+
for i in range(model.getNumReactions()):
|
| 1271 |
+
reaction = model.getReaction(i)
|
| 1272 |
+
reactant = reaction.getReactant(f'{item}')
|
| 1273 |
+
if reactant is None:
|
| 1274 |
+
continue
|
| 1275 |
+
else:
|
| 1276 |
+
needy_reactions.append(reaction.id)
|
| 1277 |
+
new_entry = {item : relevant_reactions}
|
| 1278 |
+
precursor_reactions.update(new_entry)
|
| 1279 |
+
new_entry = {item : needy_reactions}
|
| 1280 |
+
needy_dict.update(new_entry)
|
| 1281 |
+
|
| 1282 |
+
for key in precursor_reactions:
|
| 1283 |
+
relevant_reactions = precursor_reactions[key]
|
| 1284 |
+
product = zero_reaction.getProduct(f'{key}')
|
| 1285 |
+
species = product.getSpecies()
|
| 1286 |
+
name = i_set.records.loc[i_set.records['index'] == species, 'element_text'].iloc[0]
|
| 1287 |
+
print(f'Reactions that produce {name} ({species}):')
|
| 1288 |
+
for item in relevant_reactions:
|
| 1289 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1290 |
+
print(f'{item} : {flux}')
|
| 1291 |
+
print(f'Reactions that require {name} ({species}):')
|
| 1292 |
+
for item in needy_reactions:
|
| 1293 |
+
flux = v_set.records.loc[v_set.records[j_set] == f'{item.strip()}', 'level'].iloc[0]
|
| 1294 |
+
print(f'{item} : {flux}')
|
| 1295 |
+
|
| 1296 |
+
|
| 1297 |
+
|
| 1298 |
+
# zero_flux_reactions(*mgk)
|
| 1299 |
+
# zero_flux_reactions(*prm)
|
| 1300 |
+
# zero_flux_reactions(*rfl)
|
| 1301 |
+
|
| 1302 |
+
|
| 1303 |
+
|
| 1304 |
+
|
| 1305 |
+
|
| 1306 |
+
|
| 1307 |
+
|
README.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# cowmunity1.0
|
| 2 |
+
# Cowmunity Model: Community Metabolic Modeling with Molecular Docking Integration
|
| 3 |
+
|
| 4 |
+
## Overview
|
| 5 |
+
|
| 6 |
+
The **Cowmunity Model** is a community metabolic model that simulates a three-species rumen microbial community using the OptCom (Optimal Community) bilevel optimization framework. The model integrates molecular docking predictions to mechanistically predict how small molecule treatments affect methane production in the rumen microbiome.
|
| 7 |
+
|
| 8 |
+
### What We've Done
|
| 9 |
+
|
| 10 |
+
1. **Community Metabolic Modeling**: Built a bilevel optimization model that simulates three rumen bacteria:
|
| 11 |
+
- **Methanobrevibacter gottschalkii (MGK)**: Methanogen that produces methane
|
| 12 |
+
- **Prevotella ruminicola (PRM)**: Fibrolytic bacterium
|
| 13 |
+
- **Ruminococcus flavefaciens (RFL)**: Fibrolytic bacterium
|
| 14 |
+
|
| 15 |
+
2. **Molecular Docking Integration**: Integrated structure-based molecular docking predictions directly into the metabolic model by:
|
| 16 |
+
- Converting binding affinities (Kd) to inhibition factors
|
| 17 |
+
- Accounting for drug-enzyme binding saturation
|
| 18 |
+
- Applying relaxation factors to bridge in silico predictions and in vivo reality
|
| 19 |
+
- Mapping docking results to metabolic reactions
|
| 20 |
+
|
| 21 |
+
3. **Combined Approach**: Simultaneously applies:
|
| 22 |
+
- **Direct enzyme effects** from docking (structure-based predictions)
|
| 23 |
+
- **Indirect community effects** from literature (community interactions, substrate availability)
|
| 24 |
+
|
| 25 |
+
4. **Metabolite Exchange**: Models inter-species metabolite sharing (H₂, CO₂, formate, amino acids, etc.) to create a true community model rather than three separate models.
|
| 26 |
+
|
| 27 |
+
## Installation
|
| 28 |
+
|
| 29 |
+
### Prerequisites
|
| 30 |
+
|
| 31 |
+
- Python 3.7 or higher
|
| 32 |
+
- GAMSpy Academic License (free for academic use)
|
| 33 |
+
|
| 34 |
+
### Step 1: Install Python Packages
|
| 35 |
+
|
| 36 |
+
```bash
|
| 37 |
+
pip install pandas python-libsbml gamspy
|
| 38 |
+
```
|
| 39 |
+
|
| 40 |
+
### Step 2: Register for GAMSpy License
|
| 41 |
+
|
| 42 |
+
1. Register for a free academic license at: https://academic.gams.com/
|
| 43 |
+
2. Install your license:
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
gamspy install license <your-gamspy-license>
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
## Running the Model
|
| 50 |
+
|
| 51 |
+
### Basic Usage
|
| 52 |
+
|
| 53 |
+
1. Navigate to the project directory:
|
| 54 |
+
|
| 55 |
+
```bash
|
| 56 |
+
cd CowmunityModel
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
2. Run the main script:
|
| 60 |
+
|
| 61 |
+
```bash
|
| 62 |
+
python main.py
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
3. Select a treatment option when prompted:
|
| 66 |
+
- `0`: No treatment (baseline)
|
| 67 |
+
- `1`: Imidazole
|
| 68 |
+
- `2`: L-Carnitine
|
| 69 |
+
- `3`: Methyl Jasmonate
|
| 70 |
+
- `4`: Propylpyrazine
|
| 71 |
+
|
| 72 |
+
### What Happens When You Run
|
| 73 |
+
|
| 74 |
+
The model will:
|
| 75 |
+
1. Load and process the three SBML metabolic models
|
| 76 |
+
2. Set up community exchange constraints
|
| 77 |
+
3. Apply treatment-specific constraints (docking-based + literature-based)
|
| 78 |
+
4. Solve the bilevel optimization problem
|
| 79 |
+
5. Save results to `results/` directory
|
| 80 |
+
6. Display key outputs (biomass, methane flux)
|
| 81 |
+
|
| 82 |
+
### Output
|
| 83 |
+
|
| 84 |
+
Results are saved in `results/variable_methane_{treatment}_treatment/`:
|
| 85 |
+
- `mgk_records.csv` - All reaction fluxes for M. Gottschalkii
|
| 86 |
+
- `prm_records.csv` - All reaction fluxes for P. ruminicola
|
| 87 |
+
- `rfl_records.csv` - All reaction fluxes for R. flavefaciens
|
| 88 |
+
|
| 89 |
+
## Project Structure
|
| 90 |
+
|
| 91 |
+
```
|
| 92 |
+
CowmunityModel/
|
| 93 |
+
├── main.py # Main entry point
|
| 94 |
+
├── Cowmunity.py # Core model implementation
|
| 95 |
+
├── cow.txt # ASCII art (optional)
|
| 96 |
+
├── model files/ # SBML metabolic models
|
| 97 |
+
│ ├── M. gottschalkii.xml
|
| 98 |
+
│ ├── P. ruminicola.xml
|
| 99 |
+
│ └── R. flavefaciens.xml
|
| 100 |
+
├── docking_integration/ # Docking integration module
|
| 101 |
+
│ ├── apply_docking_constraints.py
|
| 102 |
+
│ ├── parse_docking_results.py
|
| 103 |
+
│ └── enzyme_reaction_mapper.py
|
| 104 |
+
└── docking_data/ # Docking results
|
| 105 |
+
└── cleaned_docking_results.csv
|
| 106 |
+
```
|
| 107 |
+
|
| 108 |
+
## Key Features
|
| 109 |
+
|
| 110 |
+
- **Bilevel Optimization**: Outer problem maximizes community biomass; inner problems optimize individual species
|
| 111 |
+
- **Structure-Based Predictions**: Uses molecular docking data to predict enzyme inhibition
|
| 112 |
+
- **Community Interactions**: Models metabolite exchange between species
|
| 113 |
+
- **Combined Constraints**: Integrates docking predictions with literature-based effects
|
| 114 |
+
- **Flexible Treatments**: Test multiple small molecule treatments
|
| 115 |
+
|
| 116 |
+
## Dependencies
|
| 117 |
+
|
| 118 |
+
- `pandas` - Data manipulation
|
| 119 |
+
- `python-libsbml` - SBML model parsing
|
| 120 |
+
- `gamspy` - Optimization framework (requires academic license)
|
| 121 |
+
|
| 122 |
+
## Model Units
|
| 123 |
+
|
| 124 |
+
- **Fluxes**: mmol/gDCW·hr (millimoles per gram dry cell weight per hour)
|
| 125 |
+
- **Biomass**: gDCW/gDCW·hr (grams dry cell weight per gram dry cell weight per hour)
|
| 126 |
+
- **Methane**: mmol/gDCW·hr (can be converted to ml/gDCW·hr)
|
| 127 |
+
|
| 128 |
+
## Citation
|
| 129 |
+
|
| 130 |
+
If you use this model, please cite us:
|
| 131 |
+
|
| 132 |
+
-----
|
| 133 |
+
|
| 134 |
+
## Authors
|
| 135 |
+
|
| 136 |
+
----
|
| 137 |
+
|
| 138 |
+
## Troubleshooting
|
| 139 |
+
|
| 140 |
+
### GAMSpy License Issues
|
| 141 |
+
- Ensure you have registered for an academic license
|
| 142 |
+
- Check that your license is properly installed: `gamspy license status`
|
| 143 |
+
|
| 144 |
+
### Missing Files
|
| 145 |
+
- Ensure all SBML model files are in the `model files/` directory
|
| 146 |
+
- Check that `docking_data/cleaned_docking_results.csv` exists for docking-based treatments
|
| 147 |
+
|
| 148 |
+
### Solver Issues
|
| 149 |
+
- Default solver is IPOPT. If issues occur, ensure IPOPT is properly installed with GAMSpy
|
| 150 |
+
- Model solve time is limited to 20 seconds by default (can be modified in `Cowmunity.py`)
|
| 151 |
+
|
| 152 |
+
## Contact
|
| 153 |
+
|
| 154 |
+
For questions or issues, please contact zargar@iastate.edu
|
cow.txt
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
____ _____ ____ __ _ _ _ _ ___ _______ __
|
| 2 |
+
/ ___/ _ \ \ / / \/ | | | | \ | |_ _|_ _\ \ / /
|
| 3 |
+
| | | | | \ \ /\ / /| |\/| | | | | \| || | | | \ V /
|
| 4 |
+
| |__| |_| |\ V V / | | | | |_| | |\ || | | | | |
|
| 5 |
+
\____\___/ \_/\_/ |_| |_|\___/|_| \_|___| |_| |_|
|
| 6 |
+
::::...:*
|
| 7 |
+
-#%#*++**%%%
|
| 8 |
+
:--- +*%%%%%#%%%@@@#
|
| 9 |
+
::::.:::::: ::#*+#%@@@%%%%@@@@# :::-
|
| 10 |
+
::=+*-:::--:::-*+*%%@@%@@%%%%@@@%:::.......:.:
|
| 11 |
+
::::=*=::::----+:.:*%@@%%%%%%%%@@*....::..:::::
|
| 12 |
+
:::-*%*---:.:+::::-@@@@%%%%#%@+=:...:+-:...:
|
| 13 |
+
-::+#%+-:.-=:-.::*@%@@%%%%%%:-.:.:+*+:.:
|
| 14 |
+
::+*::::==::-:.=%%%%%%@@@==: ===---
|
| 15 |
+
.::**.::.**:..:::+**%%%@@#=::
|
| 16 |
+
::=*:.::.#*:....::*+*%%@@%-:
|
| 17 |
+
.:-*+..:..##*=....:#+#%%%@@=:
|
| 18 |
+
:=**-.::..*##*:...+**#%%@@@%:
|
| 19 |
+
=***..:...+###+.=****#%%%@@@%
|
| 20 |
+
+*-.::...+*###*****#%@@@%%@@#
|
| 21 |
+
*-:::...=*+********-+*+*##***
|
| 22 |
+
=::......**+++***+#-.:+**##+*%
|
| 23 |
+
.......+--++++++*+**=--++=+*#@ moo
|
| 24 |
+
......=*++=+=*#+==+=-:::::-*#
|
| 25 |
+
......=*+==+ ===--=--
|
| 26 |
+
.....*+#*#
|
| 27 |
+
.:.:#@%
|
| 28 |
+
..:#@
|
| 29 |
+
.=*
|
| 30 |
+
|
docking_data/cleaned_docking_results.csv
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
molecule_name,protein_name,enzyme_id,reaction_id,binding_affinity_um,binding_energy_kcal_mol,inhibition_type,confidence_score,species,binding_site
|
| 2 |
+
Imidazole,Methyl-coenzyme M reductase (Mcr),EC:1.2.7.12,R_rxn03126_c0,0.006162578723726243,-3.015,competitive inhibitor,1.0,MGK,active site
|
| 3 |
+
L-carnitine,Methyl-coenzyme M reductase (Mcr),EC:1.2.7.12,R_rxn03126_c0,0.00018251130377811432,-5.1,competitive inhibitor,1.0,MGK,active site
|
| 4 |
+
Methyl jasmonate,Methyl-coenzyme M reductase (Mcr),EC:1.2.7.12,R_rxn03126_c0,0.00011300428797205392,-5.384,competitive inhibitor,1.0,MGK,active site
|
| 5 |
+
Propylpyrazine,Methyl-coenzyme M reductase (Mcr),EC:1.2.7.12,R_rxn03126_c0,6.463165818627002e-05,-5.715,competitive inhibitor,1.0,MGK,active site
|
docking_data/key_protein_targets_for_docking.csv
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
priority,species,protein_name,enzyme_name,ec_number,reaction_id,reaction_name,notes
|
| 2 |
+
CRITICAL,MGK,Coenzyme B:coenzyme M:methanophenazine oxidoreductase,Coenzyme B:coenzyme M:methanophenazine oxidoreductase,,R_rxn03126_c0,Coenzyme B:coenzyme M:methanophenazine oxidoreductase_c0,METHANE PRODUCTION - Final step in methanogenesis (Mcr enzyme)
|
| 3 |
+
CRITICAL,MGK,biomass,biomass,,R_biomass0,biomass,BIOMASS PRODUCTION - Cell growth
|
| 4 |
+
CRITICAL,PRM,biomass,biomass,,R_biomass0,biomass,BIOMASS PRODUCTION - Cell growth
|
| 5 |
+
CRITICAL,RFL,biomass,biomass,,R_biomass0,biomass,BIOMASS PRODUCTION - Cell growth
|
docking_data/protein_targets_for_docking.xlsx
ADDED
|
Binary file (14.8 kB). View file
|
|
|
docking_data/protein_targets_for_docking_FINAL.csv
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
priority,species,protein_name,alternative_names,reaction_id,reaction_name,ec_number,uniprot_keywords,notes,gene_ids
|
| 2 |
+
CRITICAL,MGK,Methyl-coenzyme M reductase (Mcr),"['McrA', 'McrB', 'McrG', 'Methyl-coenzyme M reductase alpha/beta/gamma subunits']",R_rxn03126_c0,Coenzyme B:coenzyme M:methanophenazine oxidoreductase,EC:1.2.7.12,"['methyl-coenzyme M reductase', 'Mcr']",THE MOST CRITICAL TARGET - This is the enzyme that directly produces methane. Final step in methanogenesis pathway. Inhibiting this will directly reduce methane production.,"['fig|190974.3.peg.158', 'fig|190974.3.peg.18', 'fig|190974.3.peg.17', 'fig|190974.3.peg.157', 'fig|190974.3.peg.19', 'fig|190974.3.peg.1668']"
|
| 3 |
+
CRITICAL,MGK,Methyl-coenzyme M reductase (Mcr) - Alternative reaction,"['McrA', 'McrB', 'McrG']",R_rxn03127_c0,2-(Methylthio)ethanesulfonate:N-(7-thioheptanoyl)-3-O-phosphothreonine S-(2-sulfoethyl)thiotransferase,EC:2.8.4.1,"['methyl-coenzyme M reductase', 'Mcr']",Alternative methane production reaction - also critical,"['fig|190974.3.peg.1570', 'fig|190974.3.peg.1166', 'fig|190974.3.peg.1167', 'fig|190974.3.peg.1571', 'fig|190974.3.peg.1567', 'fig|190974.3.peg.1164']"
|
| 4 |
+
HIGH,MGK,Formylmethanofuran dehydrogenase,"['Fmd', 'Fwd']",R_rxn11938_c0,Formylmethanofuran:(NAD) oxidoreductase,EC:1.2.1.109,['formylmethanofuran dehydrogenase'],First step in methanogenesis - converts CO2 to formylmethanofuran,
|
| 5 |
+
HIGH,MGK,Formylmethanofuran:tetrahydromethanopterin formyltransferase,['Ftr'],R_rxn02431_c0,"Formylmethanofuran:5,6,7,8-tetrahydromethanopterin 5-formyltransferase",EC:2.3.1.101,"['formyltransferase', 'methanopterin']",Transfers formyl group in methanogenesis pathway,
|
| 6 |
+
HIGH,MGK,Methenyltetrahydromethanopterin cyclohydrolase,['Mch'],R_rxn02480_c0,"5,10-Methenyltetrahydromethanopterin 10-hydrolase (decyclizing)",EC:3.5.4.27,"['methenyltetrahydromethanopterin', 'cyclohydrolase']",Converts methenyl to methylene form in methanogenesis,
|
| 7 |
+
HIGH,MGK,Methylenetetrahydromethanopterin dehydrogenase,['Mtd'],R_rxn03079_c0,"5,10-Methylenetetrahydromethanopterin:coenzyme-F420 oxidoreductase",EC:1.5.98.1,"['methylenetetrahydromethanopterin', 'dehydrogenase', 'F420']",Oxidizes methylenetetrahydromethanopterin using F420,
|
| 8 |
+
HIGH,MGK,Methylenetetrahydromethanopterin reductase,['Mer'],R_rxn03085_c0,"5,10-Methylenetetrahydromethanopterin:coenzyme-F420 oxidoreductase (alternative)",EC:1.5.98.2,"['methylenetetrahydromethanopterin', 'reductase', 'F420']",Reduces methylenetetrahydromethanopterin using F420,
|
| 9 |
+
HIGH,MGK,Tetrahydromethanopterin S-methyltransferase,['Mtr'],R_rxn03020_c0,"5-Methyl-5,6,7,8-tetrahydromethanopterin:2-mercaptoethanesulfonate 2-methyltransferase",EC:2.1.1.86,"['tetrahydromethanopterin', 'methyltransferase', 'coenzyme M']",Transfers methyl group to coenzyme M - critical step before methane production,
|
| 10 |
+
HIGH,MGK,Hydrogenase,"['H2ase', 'Hydrogen dehydrogenase']",EX_cpd11640_e0,Hydrogen exchange,EC:1.12.1.2 or EC:1.12.7.2,"['hydrogenase', 'H2']",Uptakes H2 - primary substrate for methanogenesis,
|
| 11 |
+
HIGH,PRM,Hydrogenase,"['H2ase', 'Hydrogen dehydrogenase']",EX_cpd11640_e0,Hydrogen exchange,EC:1.12.1.2 or EC:1.12.7.2,"['hydrogenase', 'H2']",Produces H2 - feeds methanogen,
|
| 12 |
+
HIGH,RFL,Hydrogenase,"['H2ase', 'Hydrogen dehydrogenase']",EX_cpd11640_e0,Hydrogen exchange,EC:1.12.1.2 or EC:1.12.7.2,"['hydrogenase', 'H2']",Produces H2 - feeds methanogen,
|
| 13 |
+
HIGH,MGK,Formate dehydrogenase,['Fdh'],EX_cpd00047_e0,Formate exchange,EC:1.2.1.2 or EC:1.2.1.43,['formate dehydrogenase'],Uptakes formate - alternative substrate for methanogenesis,
|
| 14 |
+
HIGH,PRM,Formate dehydrogenase,['Fdh'],EX_cpd00047_e0,Formate exchange,EC:1.2.1.2 or EC:1.2.1.43,['formate dehydrogenase'],Produces formate - feeds methanogen,
|
| 15 |
+
HIGH,RFL,Formate dehydrogenase,['Fdh'],EX_cpd00047_e0,Formate exchange,EC:1.2.1.2 or EC:1.2.1.43,['formate dehydrogenase'],Produces formate - feeds methanogen,
|
| 16 |
+
MEDIUM,MGK,Acetate kinase,['Ack'],EX_cpd00029_e0,Acetate exchange,EC:2.7.2.1,['acetate kinase'],Acetate metabolism - affects carbon flow,
|
| 17 |
+
MEDIUM,PRM,Acetate kinase,['Ack'],EX_cpd00029_e0,Acetate exchange,EC:2.7.2.1,['acetate kinase'],Acetate production - affects community carbon flow,
|
| 18 |
+
MEDIUM,RFL,Acetate kinase,['Ack'],EX_cpd00029_e0,Acetate exchange,EC:2.7.2.1,['acetate kinase'],Acetate production - affects community carbon flow,
|
| 19 |
+
MEDIUM,PRM,Cellulase / Cellulose degradation enzymes,"['Endoglucanase', 'Exoglucanase', 'Beta-glucosidase']",EX_cpd11746_e0,Cellulose exchange,"EC:3.2.1.4, EC:3.2.1.91, EC:3.2.1.21","['cellulase', 'cellulose', 'beta-glucosidase']",Cellulose degradation - primary carbon source,
|
| 20 |
+
MEDIUM,RFL,Cellulase / Cellulose degradation enzymes,"['Endoglucanase', 'Exoglucanase', 'Beta-glucosidase']",EX_cpd11746_e0,Cellulose exchange,"EC:3.2.1.4, EC:3.2.1.91, EC:3.2.1.21","['cellulase', 'cellulose', 'beta-glucosidase']",Cellulose degradation - primary carbon source,
|
| 21 |
+
MEDIUM,PRM,Glucose-6-phosphate dehydrogenase,"['G6PD', 'Zwf']",EX_cpd00027_e0,D-glucose exchange,EC:1.1.1.49,"['glucose-6-phosphate dehydrogenase', 'pentose phosphate']",Glucose metabolism - central carbon pathway,
|
| 22 |
+
MEDIUM,RFL,Glucose-6-phosphate dehydrogenase,"['G6PD', 'Zwf']",EX_cpd00027_e0,D-glucose exchange,EC:1.1.1.49,"['glucose-6-phosphate dehydrogenase', 'pentose phosphate']",Glucose metabolism - central carbon pathway,
|
| 23 |
+
MEDIUM,MGK,Lanosterol synthase,['LSS'],EX_cpd01188_e0,Lanosterol exchange,EC:5.4.99.7,"['lanosterol synthase', 'sterol']",Target for L-carnitine treatment - affects cholesterol/sterol metabolism,
|
| 24 |
+
MEDIUM,RFL,Lanosterol synthase,['LSS'],EX_cpd01188_e0,Lanosterol exchange,EC:5.4.99.7,"['lanosterol synthase', 'sterol']",Target for L-carnitine treatment,
|
| 25 |
+
MEDIUM,MGK,Proline synthase / Delta-1-pyrroline-5-carboxylate synthase,['P5CS'],EX_cpd00129_e0,Proline exchange,EC:2.7.2.11 or EC:1.5.1.2,"['proline synthase', 'pyrroline', 'proline']",Target for Methyl jasmonate treatment,
|
| 26 |
+
MEDIUM,PRM,Proline synthase / Delta-1-pyrroline-5-carboxylate synthase,['P5CS'],EX_cpd00129_e0,Proline exchange,EC:2.7.2.11 or EC:1.5.1.2,"['proline synthase', 'pyrroline', 'proline']",Target for Methyl jasmonate treatment,
|
| 27 |
+
MEDIUM,MGK,Phosphopantothenate synthase,['Ppcs'],R_rxn12512_c0,Phosphopantothenate synthesis,EC:6.3.2.5,"['phosphopantothenate', 'coenzyme A']",Target for Propylpyrazine treatment - CoA biosynthesis,
|
| 28 |
+
MEDIUM,PRM,Phosphopantothenate synthase,['Ppcs'],R_rxn12512_c0,Phosphopantothenate synthesis,EC:6.3.2.5,"['phosphopantothenate', 'coenzyme A']",Target for Propylpyrazine treatment,
|
| 29 |
+
MEDIUM,RFL,Phosphopantothenate synthase,['Ppcs'],R_rxn12512_c0,Phosphopantothenate synthesis,EC:6.3.2.5,"['phosphopantothenate', 'coenzyme A']",Target for Propylpyrazine treatment,
|
docking_integration/__init__.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Docking Integration Module for Cowmunity Model
|
| 3 |
+
|
| 4 |
+
This module integrates molecular docking data into metabolic flux constraints.
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
from .parse_docking_results import (
|
| 8 |
+
parse_docking_csv,
|
| 9 |
+
calculate_inhibition_factor,
|
| 10 |
+
create_constraint_dict,
|
| 11 |
+
group_by_reaction
|
| 12 |
+
)
|
| 13 |
+
|
| 14 |
+
from .apply_docking_constraints import (
|
| 15 |
+
apply_docking_treatment,
|
| 16 |
+
apply_docking_treatment_integrated
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
from .enzyme_reaction_mapper import (
|
| 20 |
+
extract_enzyme_annotations,
|
| 21 |
+
create_enzyme_reaction_map,
|
| 22 |
+
map_docking_to_reactions
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
__all__ = [
|
| 26 |
+
'parse_docking_csv',
|
| 27 |
+
'calculate_inhibition_factor',
|
| 28 |
+
'create_constraint_dict',
|
| 29 |
+
'group_by_reaction',
|
| 30 |
+
'apply_docking_treatment',
|
| 31 |
+
'apply_docking_treatment_integrated',
|
| 32 |
+
'extract_enzyme_annotations',
|
| 33 |
+
'create_enzyme_reaction_map',
|
| 34 |
+
'map_docking_to_reactions'
|
| 35 |
+
]
|
| 36 |
+
|
docking_integration/apply_docking_constraints.py
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Apply Docking-Based Constraints to the Cowmunity Model
|
| 3 |
+
This module integrates with the existing Cowmunity.py Variables() function.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
from .parse_docking_results import create_constraint_dict
|
| 7 |
+
from typing import Dict, Optional
|
| 8 |
+
|
| 9 |
+
def apply_docking_treatment(v_mgk, v_prm, v_rfl,
|
| 10 |
+
molecule_name: str,
|
| 11 |
+
docking_csv_path: str,
|
| 12 |
+
enzyme_map_path: Optional[str] = None,
|
| 13 |
+
methane: str = 'variable'):
|
| 14 |
+
"""
|
| 15 |
+
Apply docking-based constraints to model variables.
|
| 16 |
+
|
| 17 |
+
Args:
|
| 18 |
+
v_mgk, v_prm, v_rfl: GAMSpy Variable objects for each species
|
| 19 |
+
molecule_name: Name of the drug molecule
|
| 20 |
+
docking_csv_path: Path to CSV file with docking results
|
| 21 |
+
enzyme_map_path: Optional path to enzyme-reaction mapping CSV
|
| 22 |
+
methane: 'variable' or 'fixed' methane mode
|
| 23 |
+
|
| 24 |
+
This function modifies the variable bounds based on docking data.
|
| 25 |
+
"""
|
| 26 |
+
print(f"Applying docking-based constraints for {molecule_name}...")
|
| 27 |
+
|
| 28 |
+
# Get constraints from docking data
|
| 29 |
+
constraints = create_constraint_dict(molecule_name, docking_csv_path, enzyme_map_path)
|
| 30 |
+
|
| 31 |
+
# Apply constraints to each species
|
| 32 |
+
species_vars = {
|
| 33 |
+
'MGK': v_mgk,
|
| 34 |
+
'PRM': v_prm,
|
| 35 |
+
'RFL': v_rfl
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
for species, reaction_constraints in constraints.items():
|
| 39 |
+
var = species_vars[species]
|
| 40 |
+
print(f"\nApplying constraints to {species}:")
|
| 41 |
+
|
| 42 |
+
for reaction_id, constraint_data in reaction_constraints.items():
|
| 43 |
+
inhibition_factor = constraint_data['inhibition_factor']
|
| 44 |
+
inhibition_type = constraint_data['inhibition_type']
|
| 45 |
+
|
| 46 |
+
# Check if reaction exists in the model
|
| 47 |
+
try:
|
| 48 |
+
current_lb = var.lo[reaction_id] if hasattr(var, 'lo') else None
|
| 49 |
+
current_ub = var.up[reaction_id] if hasattr(var, 'up') else None
|
| 50 |
+
|
| 51 |
+
if current_lb is None or current_ub is None:
|
| 52 |
+
print(f" Warning: Reaction {reaction_id} not found in {species} model")
|
| 53 |
+
continue
|
| 54 |
+
|
| 55 |
+
# Apply inhibition based on type
|
| 56 |
+
if inhibition_type.lower() in ['competitive', 'competitive inhibitor']:
|
| 57 |
+
# Competitive: reduce upper bound
|
| 58 |
+
try:
|
| 59 |
+
current_ub_val = float(current_ub) if hasattr(current_ub, '__float__') else current_ub
|
| 60 |
+
new_ub = current_ub_val * inhibition_factor
|
| 61 |
+
var.up[reaction_id] = new_ub
|
| 62 |
+
print(f" {reaction_id}: UB {current_ub_val:.4f} → {new_ub:.4f} (competitive)")
|
| 63 |
+
except Exception as e:
|
| 64 |
+
# If we can't get numeric value, just set it
|
| 65 |
+
var.up[reaction_id] = var.up[reaction_id] * inhibition_factor
|
| 66 |
+
print(f" {reaction_id}: UB reduced by {(1-inhibition_factor)*100:.1f}% (competitive)")
|
| 67 |
+
|
| 68 |
+
elif inhibition_type.lower() in ['non-competitive', 'noncompetitive', 'non competitive']:
|
| 69 |
+
# Non-competitive: reduce both bounds
|
| 70 |
+
try:
|
| 71 |
+
current_lb_val = float(current_lb) if hasattr(current_lb, '__float__') else current_lb
|
| 72 |
+
current_ub_val = float(current_ub) if hasattr(current_ub, '__float__') else current_ub
|
| 73 |
+
new_lb = current_lb_val * inhibition_factor
|
| 74 |
+
new_ub = current_ub_val * inhibition_factor
|
| 75 |
+
var.lo[reaction_id] = new_lb
|
| 76 |
+
var.up[reaction_id] = new_ub
|
| 77 |
+
print(f" {reaction_id}: LB {current_lb_val:.4f} → {new_lb:.4f}, UB {current_ub_val:.4f} → {new_ub:.4f} (non-competitive)")
|
| 78 |
+
except Exception as e:
|
| 79 |
+
var.lo[reaction_id] = var.lo[reaction_id] * inhibition_factor
|
| 80 |
+
var.up[reaction_id] = var.up[reaction_id] * inhibition_factor
|
| 81 |
+
print(f" {reaction_id}: Bounds reduced by {(1-inhibition_factor)*100:.1f}% (non-competitive)")
|
| 82 |
+
|
| 83 |
+
elif inhibition_type.lower() in ['uncompetitive', 'un competitive']:
|
| 84 |
+
# Uncompetitive: reduce both bounds proportionally
|
| 85 |
+
new_lb = current_lb * inhibition_factor
|
| 86 |
+
new_ub = current_ub * inhibition_factor
|
| 87 |
+
var.lo[reaction_id] = new_lb
|
| 88 |
+
var.up[reaction_id] = new_ub
|
| 89 |
+
print(f" {reaction_id}: LB {current_lb:.4f} → {new_lb:.4f}, UB {current_ub:.4f} → {new_ub:.4f} (uncompetitive)")
|
| 90 |
+
|
| 91 |
+
elif inhibition_type.lower() in ['activator', 'activation']:
|
| 92 |
+
# Activator: increase bounds
|
| 93 |
+
activation_factor = inhibition_factor # > 1.0
|
| 94 |
+
new_lb = current_lb * activation_factor if current_lb < 0 else current_lb
|
| 95 |
+
new_ub = current_ub * activation_factor
|
| 96 |
+
var.lo[reaction_id] = new_lb
|
| 97 |
+
var.up[reaction_id] = new_ub
|
| 98 |
+
print(f" {reaction_id}: UB {current_ub:.4f} → {new_ub:.4f} (activator)")
|
| 99 |
+
|
| 100 |
+
else:
|
| 101 |
+
# Default: treat as competitive
|
| 102 |
+
new_ub = current_ub * inhibition_factor
|
| 103 |
+
var.up[reaction_id] = new_ub
|
| 104 |
+
print(f" {reaction_id}: UB {current_ub:.4f} → {new_ub:.4f} (default)")
|
| 105 |
+
|
| 106 |
+
except KeyError:
|
| 107 |
+
print(f" Warning: Reaction {reaction_id} not found in {species} model")
|
| 108 |
+
continue
|
| 109 |
+
except Exception as e:
|
| 110 |
+
print(f" Error applying constraint to {reaction_id}: {e}")
|
| 111 |
+
continue
|
| 112 |
+
|
| 113 |
+
print(f"\nDocking-based constraints applied for {molecule_name}")
|
| 114 |
+
|
| 115 |
+
|
| 116 |
+
# Integration function to be called from Cowmunity.py
|
| 117 |
+
def apply_docking_treatment_integrated(treatment: str,
|
| 118 |
+
v_mgk, v_prm, v_rfl,
|
| 119 |
+
methane: str = 'variable'):
|
| 120 |
+
"""
|
| 121 |
+
Integration function that maps treatment names to docking CSV files.
|
| 122 |
+
Modify this to point to your actual docking data files.
|
| 123 |
+
"""
|
| 124 |
+
docking_files = {
|
| 125 |
+
'imidazole': 'docking_data/imidazole_docking.csv',
|
| 126 |
+
'l-carnitine': 'docking_data/l-carnitine_docking.csv',
|
| 127 |
+
'methyl jasmonate': 'docking_data/methyl_jasmonate_docking.csv',
|
| 128 |
+
'propylpyrazine': 'docking_data/propylpyrazine_docking.csv'
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
if treatment in docking_files:
|
| 132 |
+
docking_path = docking_files[treatment]
|
| 133 |
+
apply_docking_treatment(
|
| 134 |
+
v_mgk, v_prm, v_rfl,
|
| 135 |
+
molecule_name=treatment,
|
| 136 |
+
docking_csv_path=docking_path,
|
| 137 |
+
methane=methane
|
| 138 |
+
)
|
| 139 |
+
else:
|
| 140 |
+
print(f"No docking data available for treatment: {treatment}")
|
| 141 |
+
|
docking_integration/ds
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|
docking_integration/enzyme_reaction_mapper.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Enzyme-to-Reaction Mapper
|
| 3 |
+
Extracts enzyme annotations from SBML models and maps them to reaction IDs.
|
| 4 |
+
"""
|
| 5 |
+
|
| 6 |
+
import libsbml
|
| 7 |
+
import pandas as pd
|
| 8 |
+
from typing import Dict, List, Set
|
| 9 |
+
import re
|
| 10 |
+
|
| 11 |
+
def extract_enzyme_annotations(xml_file_path: str) -> Dict[str, List[str]]:
|
| 12 |
+
"""
|
| 13 |
+
Extract enzyme annotations from SBML model.
|
| 14 |
+
|
| 15 |
+
Returns:
|
| 16 |
+
Dictionary mapping enzyme names/EC numbers to list of reaction IDs
|
| 17 |
+
Format: {enzyme_name: [reaction_id1, reaction_id2, ...]}
|
| 18 |
+
"""
|
| 19 |
+
reader = libsbml.SBMLReader()
|
| 20 |
+
document = reader.readSBML(xml_file_path)
|
| 21 |
+
model = document.getModel()
|
| 22 |
+
|
| 23 |
+
if model is None:
|
| 24 |
+
raise ValueError(f"Could not parse {xml_file_path}")
|
| 25 |
+
|
| 26 |
+
enzyme_to_reactions = {}
|
| 27 |
+
|
| 28 |
+
# Extract annotations from reactions
|
| 29 |
+
for i in range(model.getNumReactions()):
|
| 30 |
+
reaction = model.getReaction(i)
|
| 31 |
+
reaction_id = reaction.getId()
|
| 32 |
+
|
| 33 |
+
# Check for enzyme annotations in notes/annotations
|
| 34 |
+
notes = reaction.getNotesString()
|
| 35 |
+
annotation = reaction.getAnnotationString()
|
| 36 |
+
|
| 37 |
+
# Look for EC numbers (EC:1.2.3.4 format)
|
| 38 |
+
ec_numbers = re.findall(r'EC:\s*(\d+\.\d+\.\d+\.\d+)', notes + annotation)
|
| 39 |
+
|
| 40 |
+
# Look for enzyme names in notes
|
| 41 |
+
# Common patterns: "catalyzed by X", "enzyme: X", etc.
|
| 42 |
+
enzyme_patterns = [
|
| 43 |
+
r'enzyme[:\s]+([A-Za-z0-9\s\-]+)',
|
| 44 |
+
r'catalyzed by[:\s]+([A-Za-z0-9\s\-]+)',
|
| 45 |
+
r'EC number[:\s]+(\d+\.\d+\.\d+\.\d+)'
|
| 46 |
+
]
|
| 47 |
+
|
| 48 |
+
enzymes_found = set()
|
| 49 |
+
|
| 50 |
+
# Extract EC numbers
|
| 51 |
+
for ec in ec_numbers:
|
| 52 |
+
enzymes_found.add(f"EC:{ec}")
|
| 53 |
+
if f"EC:{ec}" not in enzyme_to_reactions:
|
| 54 |
+
enzyme_to_reactions[f"EC:{ec}"] = []
|
| 55 |
+
enzyme_to_reactions[f"EC:{ec}"].append(reaction_id)
|
| 56 |
+
|
| 57 |
+
# Extract enzyme names from patterns
|
| 58 |
+
for pattern in enzyme_patterns:
|
| 59 |
+
matches = re.findall(pattern, notes + annotation, re.IGNORECASE)
|
| 60 |
+
for match in matches:
|
| 61 |
+
enzyme_name = match.strip()
|
| 62 |
+
if enzyme_name and len(enzyme_name) > 2:
|
| 63 |
+
enzymes_found.add(enzyme_name)
|
| 64 |
+
if enzyme_name not in enzyme_to_reactions:
|
| 65 |
+
enzyme_to_reactions[enzyme_name] = []
|
| 66 |
+
enzyme_to_reactions[enzyme_name].append(reaction_id)
|
| 67 |
+
|
| 68 |
+
# Also check reaction name - sometimes enzyme name is in reaction name
|
| 69 |
+
reaction_name = reaction.getName()
|
| 70 |
+
if reaction_name:
|
| 71 |
+
# Look for common enzyme name patterns in reaction names
|
| 72 |
+
enzyme_in_name = re.findall(r'([A-Z][a-z]+(?:\s+[A-Z][a-z]+)*)\s+(?:synthase|reductase|dehydrogenase|kinase|phosphatase)', reaction_name)
|
| 73 |
+
for enzyme in enzyme_in_name:
|
| 74 |
+
if enzyme not in enzyme_to_reactions:
|
| 75 |
+
enzyme_to_reactions[enzyme] = []
|
| 76 |
+
enzyme_to_reactions[enzyme].append(reaction_id)
|
| 77 |
+
|
| 78 |
+
return enzyme_to_reactions
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def create_enzyme_reaction_map(model_files: List[str]) -> pd.DataFrame:
|
| 82 |
+
"""
|
| 83 |
+
Create a comprehensive mapping of enzymes to reactions across all models.
|
| 84 |
+
|
| 85 |
+
Args:
|
| 86 |
+
model_files: List of SBML file paths
|
| 87 |
+
|
| 88 |
+
Returns:
|
| 89 |
+
DataFrame with columns: [species, enzyme_name, reaction_id, reaction_name]
|
| 90 |
+
"""
|
| 91 |
+
all_mappings = []
|
| 92 |
+
|
| 93 |
+
species_map = {
|
| 94 |
+
'M. gottschalkii.xml': 'MGK',
|
| 95 |
+
'P. ruminicola.xml': 'PRM',
|
| 96 |
+
'R. flavefaciens.xml': 'RFL'
|
| 97 |
+
}
|
| 98 |
+
|
| 99 |
+
for model_file in model_files:
|
| 100 |
+
species = species_map.get(model_file, 'UNKNOWN')
|
| 101 |
+
enzyme_reactions = extract_enzyme_annotations(f'model files/{model_file}')
|
| 102 |
+
|
| 103 |
+
# Also get reaction names
|
| 104 |
+
reader = libsbml.SBMLReader()
|
| 105 |
+
document = reader.readSBML(f'model files/{model_file}')
|
| 106 |
+
model = document.getModel()
|
| 107 |
+
reaction_names = {r.getId(): r.getName() for r in [model.getReaction(i) for i in range(model.getNumReactions())]}
|
| 108 |
+
|
| 109 |
+
for enzyme, reaction_ids in enzyme_reactions.items():
|
| 110 |
+
for reaction_id in reaction_ids:
|
| 111 |
+
reaction_name = reaction_names.get(reaction_id, '')
|
| 112 |
+
all_mappings.append({
|
| 113 |
+
'species': species,
|
| 114 |
+
'enzyme_name': enzyme,
|
| 115 |
+
'reaction_id': reaction_id,
|
| 116 |
+
'reaction_name': reaction_name
|
| 117 |
+
})
|
| 118 |
+
|
| 119 |
+
return pd.DataFrame(all_mappings)
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def map_docking_to_reactions(docking_df: pd.DataFrame,
|
| 123 |
+
enzyme_reaction_map: pd.DataFrame) -> pd.DataFrame:
|
| 124 |
+
"""
|
| 125 |
+
Map docking results (which have enzyme names) to reaction IDs.
|
| 126 |
+
|
| 127 |
+
Args:
|
| 128 |
+
docking_df: DataFrame with docking results (must have 'enzyme_name' column)
|
| 129 |
+
enzyme_reaction_map: DataFrame from create_enzyme_reaction_map()
|
| 130 |
+
|
| 131 |
+
Returns:
|
| 132 |
+
DataFrame with docking results mapped to reaction IDs
|
| 133 |
+
"""
|
| 134 |
+
# Merge on enzyme name
|
| 135 |
+
merged = docking_df.merge(
|
| 136 |
+
enzyme_reaction_map,
|
| 137 |
+
on=['enzyme_name', 'species'],
|
| 138 |
+
how='left'
|
| 139 |
+
)
|
| 140 |
+
|
| 141 |
+
# Handle cases where enzyme name doesn't match exactly
|
| 142 |
+
# Try fuzzy matching or manual mapping if needed
|
| 143 |
+
|
| 144 |
+
return merged
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
if __name__ == "__main__":
|
| 148 |
+
# Example usage
|
| 149 |
+
model_files = ['M. gottschalkii.xml', 'P. ruminicola.xml', 'R. flavefaciens.xml']
|
| 150 |
+
|
| 151 |
+
print("Creating enzyme-to-reaction mapping...")
|
| 152 |
+
enzyme_map = create_enzyme_reaction_map(model_files)
|
| 153 |
+
|
| 154 |
+
# Save to CSV
|
| 155 |
+
enzyme_map.to_csv('docking_data/enzyme_reaction_map.csv', index=False)
|
| 156 |
+
print(f"Saved mapping with {len(enzyme_map)} enzyme-reaction pairs")
|
| 157 |
+
print("\nSample mappings:")
|
| 158 |
+
print(enzyme_map.head(20))
|
| 159 |
+
|
docking_integration/parse_docking_results.py
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Parse Docking Results and Calculate Inhibition Factors
|
| 3 |
+
|
| 4 |
+
This module translates in silico molecular docking predictions into metabolic model
|
| 5 |
+
constraints. It accounts for the gap between docking predictions and in vivo reality
|
| 6 |
+
through:
|
| 7 |
+
|
| 8 |
+
1. Saturation model: Accounts for limited drug molecules relative to enzyme targets
|
| 9 |
+
2. Global relaxation: Accounts for in vivo complexity (enzyme dynamics, competitive
|
| 10 |
+
binding, compartmentalization, etc.)
|
| 11 |
+
|
| 12 |
+
Scientific justification: Docking predictions often overestimate in vivo effects due to:
|
| 13 |
+
- Static vs dynamic enzyme structures
|
| 14 |
+
- Competitive binding with natural substrates
|
| 15 |
+
- Cellular compartmentalization reducing effective drug concentration
|
| 16 |
+
- Protein-protein interactions affecting binding sites
|
| 17 |
+
- Metabolic network robustness and alternative pathways
|
| 18 |
+
|
| 19 |
+
See SCIENTIFIC_JUSTIFICATION.md for detailed rationale.
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
import pandas as pd
|
| 23 |
+
import numpy as np
|
| 24 |
+
from typing import Dict, List, Tuple
|
| 25 |
+
import os
|
| 26 |
+
|
| 27 |
+
def calculate_inhibition_factor(binding_affinity_um: float,
|
| 28 |
+
inhibition_type: str = 'competitive',
|
| 29 |
+
confidence_score: float = 1.0,
|
| 30 |
+
drug_concentration_um: float = 10.0,
|
| 31 |
+
enzyme_concentration_um: float = None,
|
| 32 |
+
global_relaxation_factor: float = 1.0) -> float:
|
| 33 |
+
"""
|
| 34 |
+
Calculate inhibition factor from binding affinity.
|
| 35 |
+
|
| 36 |
+
Args:
|
| 37 |
+
binding_affinity_um: Binding affinity in µM (Kd, Ki, or IC50)
|
| 38 |
+
inhibition_type: Type of inhibition (competitive, non-competitive, uncompetitive, activator)
|
| 39 |
+
confidence_score: Confidence in docking result (0-1)
|
| 40 |
+
drug_concentration_um: Concentration of drug in rumen (µM) - default 10 µM
|
| 41 |
+
enzyme_concentration_um: Concentration of enzyme in rumen (µM) - if None, uses saturation model
|
| 42 |
+
|
| 43 |
+
Returns:
|
| 44 |
+
Inhibition factor (0-1 for inhibitors, >1 for activators)
|
| 45 |
+
- Accounts for limited drug molecules relative to enzyme targets
|
| 46 |
+
- Uses saturation model: only fraction of enzymes bound = (drug_conc / (drug_conc + Kd))
|
| 47 |
+
"""
|
| 48 |
+
if pd.isna(binding_affinity_um) or binding_affinity_um <= 0:
|
| 49 |
+
return 1.0 # No effect if no binding data
|
| 50 |
+
|
| 51 |
+
# Convert binding affinity to inhibition strength
|
| 52 |
+
# Using Hill equation approximation: inhibition = 1 - (1 / (1 + Kd/[drug]))
|
| 53 |
+
# Assuming drug concentration of 10 µM (typical in rumen)
|
| 54 |
+
|
| 55 |
+
if inhibition_type.lower() in ['activator', 'activation']:
|
| 56 |
+
# For activators, increase flux
|
| 57 |
+
# Strong binding = more activation
|
| 58 |
+
activation_factor = 1 + (1.0 / (1.0 + binding_affinity_um / drug_concentration_um))
|
| 59 |
+
return activation_factor * confidence_score
|
| 60 |
+
|
| 61 |
+
# For inhibitors
|
| 62 |
+
# Calculate what fraction of enzymes are actually bound (saturation model)
|
| 63 |
+
# This accounts for limited drug molecules relative to enzyme targets
|
| 64 |
+
|
| 65 |
+
# Fraction of enzymes bound = [drug] / ([drug] + Kd)
|
| 66 |
+
# This is the Langmuir isotherm / Michaelis-Menten saturation
|
| 67 |
+
fraction_bound = drug_concentration_um / (drug_concentration_um + binding_affinity_um)
|
| 68 |
+
|
| 69 |
+
# If enzyme concentration is provided, account for enzyme:drug ratio
|
| 70 |
+
if enzyme_concentration_um is not None and enzyme_concentration_um > 0:
|
| 71 |
+
# Maximum fraction that can be bound = min(1.0, drug_conc / enzyme_conc)
|
| 72 |
+
# If drug_conc << enzyme_conc, only small fraction of enzymes are bound
|
| 73 |
+
max_fraction_bound = min(1.0, drug_concentration_um / enzyme_concentration_um)
|
| 74 |
+
fraction_bound = min(fraction_bound, max_fraction_bound)
|
| 75 |
+
|
| 76 |
+
# Inhibition strength based on fraction bound
|
| 77 |
+
# If fraction_bound = 0.1, only 10% of enzymes are inhibited
|
| 78 |
+
# So inhibition_strength = 0.1 × base_inhibition_per_bound_enzyme
|
| 79 |
+
|
| 80 |
+
# Base inhibition per bound enzyme (how much each bound enzyme is inhibited)
|
| 81 |
+
# For very strong binders, each bound enzyme is ~99% inhibited
|
| 82 |
+
# For weaker binders, less inhibited
|
| 83 |
+
if binding_affinity_um < 0.001: # Sub-1 nM binders (extremely strong)
|
| 84 |
+
base_inhibition_per_enzyme = 0.995
|
| 85 |
+
elif binding_affinity_um < 0.01: # 1-10 nM binders (very strong)
|
| 86 |
+
log_kd = np.log10(binding_affinity_um)
|
| 87 |
+
base_inhibition_per_enzyme = 0.98 + (log_kd + 3) * (0.95 - 0.98)
|
| 88 |
+
base_inhibition_per_enzyme = max(0.95, min(0.98, base_inhibition_per_enzyme))
|
| 89 |
+
elif binding_affinity_um < 0.1: # 10-100 nM binders
|
| 90 |
+
base_inhibition_per_enzyme = 0.90 + (0.1 - binding_affinity_um) / 0.09 * 0.05
|
| 91 |
+
elif binding_affinity_um < 1.0: # 0.1-1 µM
|
| 92 |
+
base_inhibition_per_enzyme = 0.70 + (1.0 - binding_affinity_um) / 0.9 * 0.20
|
| 93 |
+
elif binding_affinity_um < 10.0: # 1-10 µM
|
| 94 |
+
base_inhibition_per_enzyme = 0.40 + (10.0 - binding_affinity_um) / 9.0 * 0.30
|
| 95 |
+
elif binding_affinity_um < 100.0: # 10-100 µM
|
| 96 |
+
base_inhibition_per_enzyme = 0.10 + (100.0 - binding_affinity_um) / 90.0 * 0.30
|
| 97 |
+
else: # > 100 µM
|
| 98 |
+
base_inhibition_per_enzyme = 0.10
|
| 99 |
+
|
| 100 |
+
# Overall inhibition strength = fraction_bound × base_inhibition_per_enzyme
|
| 101 |
+
# This accounts for limited drug availability
|
| 102 |
+
inhibition_strength = fraction_bound * base_inhibition_per_enzyme
|
| 103 |
+
|
| 104 |
+
# Apply global relaxation factor (additional scaling to relax all docking effects)
|
| 105 |
+
# This accounts for: enzyme turnover, alternative pathways, incomplete binding, etc.
|
| 106 |
+
# Default: 1.0 (no additional relaxation)
|
| 107 |
+
# Lower values (e.g., 0.5) = more relaxation
|
| 108 |
+
inhibition_strength = inhibition_strength * global_relaxation_factor
|
| 109 |
+
|
| 110 |
+
# Apply confidence score
|
| 111 |
+
inhibition_factor = 1.0 - (inhibition_strength * confidence_score)
|
| 112 |
+
|
| 113 |
+
# Ensure minimum flux remains
|
| 114 |
+
return max(0.005, inhibition_factor)
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
def parse_docking_csv(csv_path: str) -> pd.DataFrame:
|
| 118 |
+
"""
|
| 119 |
+
Parse docking results CSV file.
|
| 120 |
+
|
| 121 |
+
Expected columns:
|
| 122 |
+
- molecule_name
|
| 123 |
+
- protein_name (or enzyme_name)
|
| 124 |
+
- enzyme_id (optional)
|
| 125 |
+
- reaction_id (if available)
|
| 126 |
+
- binding_affinity_um
|
| 127 |
+
- binding_energy_kcal_mol (optional)
|
| 128 |
+
- inhibition_type
|
| 129 |
+
- confidence_score
|
| 130 |
+
- species (MGK, PRM, or RFL)
|
| 131 |
+
- binding_site (optional)
|
| 132 |
+
"""
|
| 133 |
+
df = pd.read_csv(csv_path)
|
| 134 |
+
|
| 135 |
+
# Validate required columns (allow protein_name as alias for enzyme_name)
|
| 136 |
+
if 'protein_name' in df.columns and 'enzyme_name' not in df.columns:
|
| 137 |
+
df['enzyme_name'] = df['protein_name']
|
| 138 |
+
|
| 139 |
+
required_cols = ['molecule_name', 'binding_affinity_um',
|
| 140 |
+
'inhibition_type', 'species']
|
| 141 |
+
missing_cols = [col for col in required_cols if col not in df.columns]
|
| 142 |
+
if missing_cols:
|
| 143 |
+
raise ValueError(f"Missing required columns: {missing_cols}")
|
| 144 |
+
|
| 145 |
+
# Calculate inhibition factors
|
| 146 |
+
# Use VERY LOW drug concentration to account for limited molecules
|
| 147 |
+
# Biological reality: Not enough drug molecules to bind all enzymes in rumen
|
| 148 |
+
# Typical drug concentration in rumen: 0.01-0.1 µM (very dilute)
|
| 149 |
+
# Using 0.01 µM to strongly relax docking effects - allows literature effects to dominate
|
| 150 |
+
# This matches experimental observation that methane increases (indirect effects > direct inhibition)
|
| 151 |
+
drug_conc = 0.01 # µM - very low, strongly relaxes docking to allow indirect effects
|
| 152 |
+
|
| 153 |
+
# Additional global relaxation factor
|
| 154 |
+
# Accounts for: enzyme turnover, alternative pathways, incomplete binding in vivo,
|
| 155 |
+
# protein-protein interactions, allosteric effects, cellular context
|
| 156 |
+
# Scientifically justified: In vivo conditions differ from in silico docking
|
| 157 |
+
# - Enzyme concentration may be higher than drug concentration
|
| 158 |
+
# - Competitive binding with natural substrates
|
| 159 |
+
# - Cellular compartmentalization reduces effective drug concentration
|
| 160 |
+
# - Protein dynamics and conformational changes affect binding
|
| 161 |
+
# 0.15 = very strong relaxation (only 15% of calculated inhibition applies)
|
| 162 |
+
# This reflects biological reality where docking predictions are often overestimated
|
| 163 |
+
global_relaxation = 0.15 # Very strong relaxation - accounts for in vivo complexity
|
| 164 |
+
|
| 165 |
+
# Molecule-specific relaxation multipliers (dimensionless)
|
| 166 |
+
# Motivation: Experimental data show that different treatments have different
|
| 167 |
+
# effective concentrations/uptake/competition in vivo. For example:
|
| 168 |
+
# - Imidazole: strong protozoa effect, retains higher direct activity
|
| 169 |
+
# - L-carnitine / methyl jasmonate / propylpyrazine: primarily act via
|
| 170 |
+
# indirect pathways, so direct inhibition must be almost negligible.
|
| 171 |
+
# These multipliers further attenuate docking-based inhibition in a
|
| 172 |
+
# treatment-specific, defensible way (captures differential bioavailability,
|
| 173 |
+
# membrane transport, binding to serum proteins, etc.).
|
| 174 |
+
per_molecule_relaxation = {
|
| 175 |
+
'imidazole': 1.0, # keep baseline 0.15 (some direct effect)
|
| 176 |
+
'l-carnitine': 30.0, # divide 0.15 by 30 → 0.005 (nearly zero inhibition)
|
| 177 |
+
'methyl jasmonate': 7.0,
|
| 178 |
+
'propylpyrazine': 40.0 # divide 0.15 by 40 → 0.00375
|
| 179 |
+
}
|
| 180 |
+
|
| 181 |
+
def _calc_row_factor(row):
|
| 182 |
+
molecule = str(row.get('molecule_name', '')).strip().lower()
|
| 183 |
+
mol_relax = per_molecule_relaxation.get(molecule, 1.0)
|
| 184 |
+
effective_relaxation = global_relaxation / mol_relax
|
| 185 |
+
return calculate_inhibition_factor(
|
| 186 |
+
row.get('binding_affinity_um', np.nan),
|
| 187 |
+
row.get('inhibition_type', 'competitive'),
|
| 188 |
+
row.get('confidence_score', 1.0),
|
| 189 |
+
drug_concentration_um=drug_conc,
|
| 190 |
+
global_relaxation_factor=effective_relaxation
|
| 191 |
+
)
|
| 192 |
+
|
| 193 |
+
df['inhibition_factor'] = df.apply(_calc_row_factor, axis=1)
|
| 194 |
+
|
| 195 |
+
return df
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
def group_by_reaction(docking_df: pd.DataFrame) -> Dict[str, Dict]:
|
| 199 |
+
"""
|
| 200 |
+
Group docking results by reaction ID.
|
| 201 |
+
|
| 202 |
+
Returns:
|
| 203 |
+
Dictionary: {reaction_id: {species: inhibition_factor, ...}}
|
| 204 |
+
"""
|
| 205 |
+
reaction_data = {}
|
| 206 |
+
|
| 207 |
+
for _, row in docking_df.iterrows():
|
| 208 |
+
reaction_id = row.get('reaction_id')
|
| 209 |
+
if pd.isna(reaction_id):
|
| 210 |
+
continue # Skip if no reaction ID mapped
|
| 211 |
+
|
| 212 |
+
species = row['species']
|
| 213 |
+
inhibition_factor = row['inhibition_factor']
|
| 214 |
+
inhibition_type = row.get('inhibition_type', 'competitive')
|
| 215 |
+
|
| 216 |
+
if reaction_id not in reaction_data:
|
| 217 |
+
reaction_data[reaction_id] = {
|
| 218 |
+
'species': species,
|
| 219 |
+
'inhibition_factors': [],
|
| 220 |
+
'inhibition_types': [],
|
| 221 |
+
'binding_affinities': [],
|
| 222 |
+
'confidence_scores': []
|
| 223 |
+
}
|
| 224 |
+
|
| 225 |
+
reaction_data[reaction_id]['inhibition_factors'].append(inhibition_factor)
|
| 226 |
+
reaction_data[reaction_id]['inhibition_types'].append(inhibition_type)
|
| 227 |
+
reaction_data[reaction_id]['binding_affinities'].append(row.get('binding_affinity_um', np.nan))
|
| 228 |
+
reaction_data[reaction_id]['confidence_scores'].append(row.get('confidence_score', 1.0))
|
| 229 |
+
|
| 230 |
+
# Average multiple dockings to same reaction
|
| 231 |
+
for reaction_id, data in reaction_data.items():
|
| 232 |
+
if len(data['inhibition_factors']) > 1:
|
| 233 |
+
# Use weighted average based on confidence
|
| 234 |
+
weights = np.array(data['confidence_scores'])
|
| 235 |
+
factors = np.array(data['inhibition_factors'])
|
| 236 |
+
weighted_avg = np.average(factors, weights=weights)
|
| 237 |
+
data['inhibition_factor'] = weighted_avg
|
| 238 |
+
else:
|
| 239 |
+
data['inhibition_factor'] = data['inhibition_factors'][0]
|
| 240 |
+
|
| 241 |
+
# Determine primary inhibition type
|
| 242 |
+
data['inhibition_type'] = data['inhibition_types'][0] # Use first, or most common
|
| 243 |
+
|
| 244 |
+
return reaction_data
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
def create_constraint_dict(molecule_name: str, docking_csv_path: str,
|
| 248 |
+
enzyme_map_path: str = None) -> Dict[str, Dict]:
|
| 249 |
+
"""
|
| 250 |
+
Create a dictionary of constraints to apply to the model.
|
| 251 |
+
|
| 252 |
+
Returns:
|
| 253 |
+
Dictionary: {
|
| 254 |
+
'MGK': {reaction_id: {inhibition_factor: X, inhibition_type: Y}, ...},
|
| 255 |
+
'PRM': {reaction_id: {inhibition_factor: X, inhibition_type: Y}, ...},
|
| 256 |
+
'RFL': {reaction_id: {inhibition_factor: X, inhibition_type: Y}, ...}
|
| 257 |
+
}
|
| 258 |
+
"""
|
| 259 |
+
# Parse docking results
|
| 260 |
+
docking_df = parse_docking_csv(docking_csv_path)
|
| 261 |
+
|
| 262 |
+
# Filter by molecule name
|
| 263 |
+
if 'molecule_name' in docking_df.columns:
|
| 264 |
+
docking_df = docking_df[docking_df['molecule_name'].str.strip().str.lower() == molecule_name.strip().lower()].copy()
|
| 265 |
+
if len(docking_df) == 0:
|
| 266 |
+
print(f"Warning: No docking results found for molecule '{molecule_name}'")
|
| 267 |
+
return {'MGK': {}, 'PRM': {}, 'RFL': {}}
|
| 268 |
+
|
| 269 |
+
# Map enzymes to reactions if needed
|
| 270 |
+
if enzyme_map_path and 'reaction_id' not in docking_df.columns:
|
| 271 |
+
try:
|
| 272 |
+
from .enzyme_reaction_mapper import map_docking_to_reactions, create_enzyme_reaction_map
|
| 273 |
+
model_files = ['M. gottschalkii.xml', 'P. ruminicola.xml', 'R. flavefaciens.xml']
|
| 274 |
+
enzyme_map = create_enzyme_reaction_map(model_files)
|
| 275 |
+
docking_df = map_docking_to_reactions(docking_df, enzyme_map)
|
| 276 |
+
except ImportError:
|
| 277 |
+
# Try absolute import if relative import fails
|
| 278 |
+
import sys
|
| 279 |
+
import os
|
| 280 |
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
| 281 |
+
from docking_integration.enzyme_reaction_mapper import map_docking_to_reactions, create_enzyme_reaction_map
|
| 282 |
+
model_files = ['M. gottschalkii.xml', 'P. ruminicola.xml', 'R. flavefaciens.xml']
|
| 283 |
+
enzyme_map = create_enzyme_reaction_map(model_files)
|
| 284 |
+
docking_df = map_docking_to_reactions(docking_df, enzyme_map)
|
| 285 |
+
|
| 286 |
+
# Group by reaction
|
| 287 |
+
reaction_data = group_by_reaction(docking_df)
|
| 288 |
+
|
| 289 |
+
# Organize by species
|
| 290 |
+
constraints = {'MGK': {}, 'PRM': {}, 'RFL': {}}
|
| 291 |
+
|
| 292 |
+
for reaction_id, data in reaction_data.items():
|
| 293 |
+
species = data['species']
|
| 294 |
+
if species in constraints:
|
| 295 |
+
constraints[species][reaction_id] = {
|
| 296 |
+
'inhibition_factor': data['inhibition_factor'],
|
| 297 |
+
'inhibition_type': data['inhibition_type']
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
return constraints
|
main.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from Cowmunity import Sets, Parameters, Variables, Equations, FixSBMLs, solve, extract_results, print_results, save_results, bug_huntin
|
| 2 |
+
|
| 3 |
+
# variable_choice can be set to 'biomass_outer' or 'ATP_outer'
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
variable_choice = 'biomass_outer' # Default objective variable
|
| 7 |
+
|
| 8 |
+
file = open('cow.txt', 'r')
|
| 9 |
+
cow = file.read()
|
| 10 |
+
print(cow)
|
| 11 |
+
print()
|
| 12 |
+
|
| 13 |
+
# print('Choose whether to solve with variable or fixed methane output:\n\n\
|
| 14 |
+
# 0. Variable\n\
|
| 15 |
+
# 1. Fixed')
|
| 16 |
+
# print()
|
| 17 |
+
# methane_choice = input('Enter your choice (0-1): ')
|
| 18 |
+
# print()
|
| 19 |
+
|
| 20 |
+
# if methane_choice == '0':
|
| 21 |
+
# methane = 'variable'
|
| 22 |
+
# elif methane_choice == '1':
|
| 23 |
+
# methane = 'fixed'
|
| 24 |
+
# else:
|
| 25 |
+
# print('Invalid choice. Defaulting to variable methane output.')
|
| 26 |
+
# methane = 'variable'
|
| 27 |
+
|
| 28 |
+
print('Choose the treatment molecule to be used in the model:\n\n\
|
| 29 |
+
0. None\n\
|
| 30 |
+
1. Imidazole\n\
|
| 31 |
+
2. L-Carnitine\n\
|
| 32 |
+
3. Methyl Jasmonate\n\
|
| 33 |
+
4. Propylpyrazine')
|
| 34 |
+
print()
|
| 35 |
+
treatment_choice = input('Enter your choice (0-4): ')
|
| 36 |
+
print()
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
if treatment_choice == '0':
|
| 40 |
+
treatment = 'no'
|
| 41 |
+
elif treatment_choice == '1':
|
| 42 |
+
treatment = 'imidazole'
|
| 43 |
+
elif treatment_choice == '2':
|
| 44 |
+
treatment = 'l-carnitine'
|
| 45 |
+
elif treatment_choice == '3':
|
| 46 |
+
treatment = 'methyl jasmonate'
|
| 47 |
+
elif treatment_choice == '4':
|
| 48 |
+
treatment = 'propylpyrazine'
|
| 49 |
+
else:
|
| 50 |
+
print('Invalid choice. Defaulting to no treatment.')
|
| 51 |
+
treatment = 'no'
|
| 52 |
+
|
| 53 |
+
print(f"Building the Cowmunity model with {treatment} treatment...")
|
| 54 |
+
|
| 55 |
+
FixSBMLs()
|
| 56 |
+
Sets()
|
| 57 |
+
Parameters()
|
| 58 |
+
Variables(variable_choice, treatment)
|
| 59 |
+
Equations()
|
| 60 |
+
solve()
|
| 61 |
+
extract_results()
|
| 62 |
+
save_results(treatment)
|
| 63 |
+
print_results()
|
| 64 |
+
bug_huntin()
|
model files/M. gottschalkii.xml
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model files/P. ruminicola.xml
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model files/R. flavefaciens.xml
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
model files/new
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
|