strainOptimizer 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strainoptimizer-0.1.0/LICENSE +21 -0
- strainoptimizer-0.1.0/PKG-INFO +161 -0
- strainoptimizer-0.1.0/README.md +103 -0
- strainoptimizer-0.1.0/pyproject.toml +167 -0
- strainoptimizer-0.1.0/setup.cfg +4 -0
- strainoptimizer-0.1.0/src/strainOptimizer/__init__.py +12 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/FCC.py +109 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/__init__.py +4 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/dataset.py +73 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/ecGEM_utils.py +47 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/enzyme_variety_analysis.py +139 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/etfl_utils.py +54 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/flux_variety_analysis.py +1 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/model_process.py +512 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/network.py +251 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/optimal_yield.py +37 -0
- strainoptimizer-0.1.0/src/strainOptimizer/analysis/protein_process.py +737 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/analysis/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/analysis/dynamic.py +633 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/analysis/summary.py +103 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/analysis/utils.py +33 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/__init__.py +3 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/allocation.py +845 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/carbohydrate.py +36 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/dna.py +60 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/enzyme.py +152 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/expression.py +315 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/genes.py +237 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/ion.py +36 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/lipid.py +36 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/macromolecule.py +102 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/memodel.py +2163 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/reactions.py +273 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/rna.py +129 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/core/thermomemodel.py +112 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/data/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/data/ecoli.py +1064 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/data/ecoli_utils.py +65 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/debugging/__init__.py +1 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/debugging/debugging.py +400 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/integration/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/integration/transcriptomics.py +82 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/io/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/io/dict.py +938 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/io/json.py +70 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/optim/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/optim/config.py +87 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/optim/constraints.py +307 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/optim/utils.py +500 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/optim/variables.py +210 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/tests/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/tests/small_model.py +400 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/utils/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/utils/parsing.py +115 -0
- strainoptimizer-0.1.0/src/strainOptimizer/etfl/utils/utils.py +87 -0
- strainoptimizer-0.1.0/src/strainOptimizer/io.py +68 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/__init__.py +0 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/constraint/__init__.py +2 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/constraint/enzyme.py +129 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/constraint/reaction.py +11 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/constraint/total_resource_allocation.py +122 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/integration/__init__.py +1 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/integration/gimme.py +121 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/integration/proteome.py +2 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/integration/transcriptome.py +46 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/mainFunction.py +621 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/model_process.py +536 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/protein_process.py +737 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/variable/__init__.py +6 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/variable/enzyme.py +52 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/variable/metabolite.py +2 -0
- strainoptimizer-0.1.0/src/strainOptimizer/manipulation/variable/reaction.py +2 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/FBA.py +14 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/MOMA.py +152 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/MOPA.py +162 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/TFA.py +123 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/__init__.py +8 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/ecYeastFlux.py +434 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/pFBA.py +32 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/pprotFBA.py +156 -0
- strainoptimizer-0.1.0/src/strainOptimizer/simulation/utils.py +42 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/__init__.py +7 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/ecFactory/__init__.py +2 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/ecFactory/ecFactory_other.py +309 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/ecFactory/ecfseof.py +386 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/ecFactory/find_min_sets.py +109 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/ecFactory/run_ecFactory.py +424 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/iBridge/__init__.py +6 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/iBridge/ibridge.py +486 -0
- strainoptimizer-0.1.0/src/strainOptimizer/strainDesign/workflow_engine.py +396 -0
- strainoptimizer-0.1.0/src/strainOptimizer/visualization/__init__.py +1 -0
- strainoptimizer-0.1.0/src/strainOptimizer/visualization/phase_plane.py +85 -0
- strainoptimizer-0.1.0/src/strainOptimizer.egg-info/PKG-INFO +161 -0
- strainoptimizer-0.1.0/src/strainOptimizer.egg-info/SOURCES.txt +96 -0
- strainoptimizer-0.1.0/src/strainOptimizer.egg-info/dependency_links.txt +1 -0
- strainoptimizer-0.1.0/src/strainOptimizer.egg-info/requires.txt +36 -0
- strainoptimizer-0.1.0/src/strainOptimizer.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Hongzhong Lu @Shanghai Jiao Tong University
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: strainOptimizer
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Computational strain design using enzyme-constrained GEMs and ETFL models
|
|
5
|
+
Author-email: Haoyu Wang <wanghy@dicp.ac.cn>
|
|
6
|
+
Maintainer-email: Haoyu Wang <wanghy@dicp.ac.cn>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/hongzhonglu/strainOptimizer
|
|
9
|
+
Project-URL: Repository, https://github.com/hongzhonglu/strainOptimizer
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/hongzhonglu/strainOptimizer/issues
|
|
11
|
+
Project-URL: Documentation, https://github.com/hongzhonglu/strainOptimizer/blob/main/README.md
|
|
12
|
+
Project-URL: Zenodo Archive, https://doi.org/10.5281/zenodo.20770724
|
|
13
|
+
Keywords: metabolic engineering,strain design,genome-scale model,enzyme-constrained model,ecGEM,ETFL,systems biology,flux balance analysis,synthetic biology
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
17
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Operating System :: OS Independent
|
|
23
|
+
Requires-Python: <3.11,>=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: cobra==0.24.0
|
|
27
|
+
Requires-Dist: python-libsbml>=5.19.0
|
|
28
|
+
Requires-Dist: optlang==1.5.2
|
|
29
|
+
Requires-Dist: pytfa>=0.9.1
|
|
30
|
+
Requires-Dist: sympy==1.6.2
|
|
31
|
+
Requires-Dist: numpy<2.0,>=1.23
|
|
32
|
+
Requires-Dist: scipy>=1.13
|
|
33
|
+
Requires-Dist: pandas<2.0,>=1.3.5
|
|
34
|
+
Requires-Dist: matplotlib>=3.9
|
|
35
|
+
Requires-Dist: networkx>=3.2
|
|
36
|
+
Requires-Dist: biopython>=1.85
|
|
37
|
+
Requires-Dist: openpyxl>=3.1
|
|
38
|
+
Requires-Dist: xlrd>=2.0
|
|
39
|
+
Requires-Dist: pydantic<2.0,>=1.10
|
|
40
|
+
Requires-Dist: tqdm>=4.60
|
|
41
|
+
Requires-Dist: rich>=13.0
|
|
42
|
+
Requires-Dist: six>=1.16
|
|
43
|
+
Requires-Dist: python-dateutil>=2.9
|
|
44
|
+
Provides-Extra: gurobi
|
|
45
|
+
Requires-Dist: gurobipy>=10.0; extra == "gurobi"
|
|
46
|
+
Provides-Extra: cplex
|
|
47
|
+
Requires-Dist: cplex>=22.1; extra == "cplex"
|
|
48
|
+
Provides-Extra: omics
|
|
49
|
+
Requires-Dist: troppo>=0.1; extra == "omics"
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
52
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
53
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
54
|
+
Requires-Dist: ruff>=0.4; extra == "dev"
|
|
55
|
+
Provides-Extra: all
|
|
56
|
+
Requires-Dist: strainOptimizer[dev,omics]; extra == "all"
|
|
57
|
+
Dynamic: license-file
|
|
58
|
+
|
|
59
|
+
# strainOptimizer
|
|
60
|
+
|
|
61
|
+
[](https://doi.org/10.5281/zenodo.20770724)
|
|
62
|
+
|
|
63
|
+
Repo for strain design based on ETFL/ecGEM models.
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
## Overview
|
|
67
|
+
strainOptimizer is a Python package for strain design using enzyme-constrained genome-scale metabolic models (ecGEMs) and ETFL models. It implements advanced strain design algorithms such as ecFactory and ecFSEOF, which leverage the additional constraints provided by enzyme capacity to identify more realistic genetic modifications for enhanced production of target metabolites.
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
1. Clone the repo
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
git clone https://github.com/hongzhonglu/strainOptimizer.git
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
2. Set up the environment
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
conda create -n strainOpitimizer python=3.10
|
|
80
|
+
conda activate strainOpitimizer
|
|
81
|
+
conda env update --file environment.yml
|
|
82
|
+
pip install -e .
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
3. Solvers
|
|
86
|
+
|
|
87
|
+
We recommend using commercial solvers such as CPLEX or Gurobi. Please install one of them and set up the corresponding Python API.
|
|
88
|
+
- GUROBI (version 10.0)
|
|
89
|
+
|
|
90
|
+
We recommend obtaining a valid Gurobi license. Otherwise, adjust the code to use a different optimizer. To retrieve your license::
|
|
91
|
+
```
|
|
92
|
+
grbgetkey <YOUR-LICENSE-KEY>
|
|
93
|
+
```
|
|
94
|
+
For details, see the Gurobi licensing guide: https://www.gurobi.com/documentation/
|
|
95
|
+
|
|
96
|
+
- CPLEX
|
|
97
|
+
After installing CPLEX into the system, set the CPLEX Python API in your environment :
|
|
98
|
+
```
|
|
99
|
+
python [cplex_path]/python/setup.py install
|
|
100
|
+
```
|
|
101
|
+
## Usage guide
|
|
102
|
+
1. [ecFactory design example](examples/1.ecFactory_design_example.ipynb)
|
|
103
|
+
2. [ecFSEOF design example](examples/2.ecFSEOF_design_example.ipynb)
|
|
104
|
+
|
|
105
|
+
More examples can be found in the [examples](examples) folder.
|
|
106
|
+
## Example script
|
|
107
|
+
Here is an example script for 2-PE strain design:
|
|
108
|
+
```python
|
|
109
|
+
from strainOptimizer import strainOptimizer_engine,WorkflowParameters
|
|
110
|
+
|
|
111
|
+
# Model parameters - model path, type, solver, growth reaction
|
|
112
|
+
model_params = {
|
|
113
|
+
'model_path': 'example/models\yeast\ecYeastGEM_batch.xml',
|
|
114
|
+
'model_type': 'ecGEM',
|
|
115
|
+
'solver': 'optlang-gurobi',
|
|
116
|
+
'growth_id': 'r_2111',
|
|
117
|
+
}
|
|
118
|
+
# Strain parameters - target product and growth conditions
|
|
119
|
+
strain_params = {
|
|
120
|
+
'target_id': 'r_1589',
|
|
121
|
+
'product_name': '2-phenylethanol',
|
|
122
|
+
'c_source': 'r_1714_REV', # glucose exchange reaction
|
|
123
|
+
'c_uptake': 5, # glucose uptake rate (mmol/gDW/h)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Algorithm control parameters - workflow and output settings
|
|
127
|
+
algorithm_params = {
|
|
128
|
+
'design_algorithm': 'ecFactory',
|
|
129
|
+
'simulation_method': 'ppfba',
|
|
130
|
+
'experimental_yield': None, # if without experimental yield data, use the 1/2
|
|
131
|
+
'remove_essential': True,
|
|
132
|
+
'output_directory': './results',
|
|
133
|
+
'steps':123,
|
|
134
|
+
'action_thresholds':[0.05,0.3,1.1]
|
|
135
|
+
# 'save_results': False,
|
|
136
|
+
# 'only_final_result': True,
|
|
137
|
+
# Note: ecFactory-specific parameters like steps, action_thresholds, etc.
|
|
138
|
+
# would need to be added to AlgorithmControl if they're used
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# Create WorkflowParameters using the three-level structure
|
|
142
|
+
params = WorkflowParameters(
|
|
143
|
+
model=model_params,
|
|
144
|
+
strain=strain_params,
|
|
145
|
+
algorithm=algorithm_params
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Create workflow engine using the new framework
|
|
149
|
+
engine = strainOptimizer_engine(params)
|
|
150
|
+
# Load model
|
|
151
|
+
engine.load_model()
|
|
152
|
+
# Run the design workflow
|
|
153
|
+
final_result=engine.run_design()
|
|
154
|
+
# More detailed results can be accessed via engine.all_results.
|
|
155
|
+
# And results at each level have been saved in output_directory.
|
|
156
|
+
```
|
|
157
|
+
## Contribution
|
|
158
|
+
|
|
159
|
+
* For contributors: Fork it to your Github account, and create a new branch from [`dev`](https://github.com/hongzhonglu/strainOptimizer/tree/dev).
|
|
160
|
+
|
|
161
|
+
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# strainOptimizer
|
|
2
|
+
|
|
3
|
+
[](https://doi.org/10.5281/zenodo.20770724)
|
|
4
|
+
|
|
5
|
+
Repo for strain design based on ETFL/ecGEM models.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
strainOptimizer is a Python package for strain design using enzyme-constrained genome-scale metabolic models (ecGEMs) and ETFL models. It implements advanced strain design algorithms such as ecFactory and ecFSEOF, which leverage the additional constraints provided by enzyme capacity to identify more realistic genetic modifications for enhanced production of target metabolites.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
1. Clone the repo
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
git clone https://github.com/hongzhonglu/strainOptimizer.git
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
2. Set up the environment
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
conda create -n strainOpitimizer python=3.10
|
|
22
|
+
conda activate strainOpitimizer
|
|
23
|
+
conda env update --file environment.yml
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
3. Solvers
|
|
28
|
+
|
|
29
|
+
We recommend using commercial solvers such as CPLEX or Gurobi. Please install one of them and set up the corresponding Python API.
|
|
30
|
+
- GUROBI (version 10.0)
|
|
31
|
+
|
|
32
|
+
We recommend obtaining a valid Gurobi license. Otherwise, adjust the code to use a different optimizer. To retrieve your license::
|
|
33
|
+
```
|
|
34
|
+
grbgetkey <YOUR-LICENSE-KEY>
|
|
35
|
+
```
|
|
36
|
+
For details, see the Gurobi licensing guide: https://www.gurobi.com/documentation/
|
|
37
|
+
|
|
38
|
+
- CPLEX
|
|
39
|
+
After installing CPLEX into the system, set the CPLEX Python API in your environment :
|
|
40
|
+
```
|
|
41
|
+
python [cplex_path]/python/setup.py install
|
|
42
|
+
```
|
|
43
|
+
## Usage guide
|
|
44
|
+
1. [ecFactory design example](examples/1.ecFactory_design_example.ipynb)
|
|
45
|
+
2. [ecFSEOF design example](examples/2.ecFSEOF_design_example.ipynb)
|
|
46
|
+
|
|
47
|
+
More examples can be found in the [examples](examples) folder.
|
|
48
|
+
## Example script
|
|
49
|
+
Here is an example script for 2-PE strain design:
|
|
50
|
+
```python
|
|
51
|
+
from strainOptimizer import strainOptimizer_engine,WorkflowParameters
|
|
52
|
+
|
|
53
|
+
# Model parameters - model path, type, solver, growth reaction
|
|
54
|
+
model_params = {
|
|
55
|
+
'model_path': 'example/models\yeast\ecYeastGEM_batch.xml',
|
|
56
|
+
'model_type': 'ecGEM',
|
|
57
|
+
'solver': 'optlang-gurobi',
|
|
58
|
+
'growth_id': 'r_2111',
|
|
59
|
+
}
|
|
60
|
+
# Strain parameters - target product and growth conditions
|
|
61
|
+
strain_params = {
|
|
62
|
+
'target_id': 'r_1589',
|
|
63
|
+
'product_name': '2-phenylethanol',
|
|
64
|
+
'c_source': 'r_1714_REV', # glucose exchange reaction
|
|
65
|
+
'c_uptake': 5, # glucose uptake rate (mmol/gDW/h)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# Algorithm control parameters - workflow and output settings
|
|
69
|
+
algorithm_params = {
|
|
70
|
+
'design_algorithm': 'ecFactory',
|
|
71
|
+
'simulation_method': 'ppfba',
|
|
72
|
+
'experimental_yield': None, # if without experimental yield data, use the 1/2
|
|
73
|
+
'remove_essential': True,
|
|
74
|
+
'output_directory': './results',
|
|
75
|
+
'steps':123,
|
|
76
|
+
'action_thresholds':[0.05,0.3,1.1]
|
|
77
|
+
# 'save_results': False,
|
|
78
|
+
# 'only_final_result': True,
|
|
79
|
+
# Note: ecFactory-specific parameters like steps, action_thresholds, etc.
|
|
80
|
+
# would need to be added to AlgorithmControl if they're used
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# Create WorkflowParameters using the three-level structure
|
|
84
|
+
params = WorkflowParameters(
|
|
85
|
+
model=model_params,
|
|
86
|
+
strain=strain_params,
|
|
87
|
+
algorithm=algorithm_params
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Create workflow engine using the new framework
|
|
91
|
+
engine = strainOptimizer_engine(params)
|
|
92
|
+
# Load model
|
|
93
|
+
engine.load_model()
|
|
94
|
+
# Run the design workflow
|
|
95
|
+
final_result=engine.run_design()
|
|
96
|
+
# More detailed results can be accessed via engine.all_results.
|
|
97
|
+
# And results at each level have been saved in output_directory.
|
|
98
|
+
```
|
|
99
|
+
## Contribution
|
|
100
|
+
|
|
101
|
+
* For contributors: Fork it to your Github account, and create a new branch from [`dev`](https://github.com/hongzhonglu/strainOptimizer/tree/dev).
|
|
102
|
+
|
|
103
|
+
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
# ---------------------------------------------------------------------------
|
|
6
|
+
# Project metadata
|
|
7
|
+
# ---------------------------------------------------------------------------
|
|
8
|
+
[project]
|
|
9
|
+
name = "strainOptimizer"
|
|
10
|
+
version = "0.1.0"
|
|
11
|
+
description = "Computational strain design using enzyme-constrained GEMs and ETFL models"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
license = { text = "MIT" }
|
|
14
|
+
authors = [
|
|
15
|
+
{ name = "Haoyu Wang", email = "wanghy@dicp.ac.cn" },
|
|
16
|
+
]
|
|
17
|
+
maintainers = [
|
|
18
|
+
{ name = "Haoyu Wang", email = "wanghy@dicp.ac.cn" },
|
|
19
|
+
]
|
|
20
|
+
keywords = [
|
|
21
|
+
"metabolic engineering",
|
|
22
|
+
"strain design",
|
|
23
|
+
"genome-scale model",
|
|
24
|
+
"enzyme-constrained model",
|
|
25
|
+
"ecGEM",
|
|
26
|
+
"ETFL",
|
|
27
|
+
"systems biology",
|
|
28
|
+
"flux balance analysis",
|
|
29
|
+
"synthetic biology",
|
|
30
|
+
]
|
|
31
|
+
classifiers = [
|
|
32
|
+
"Development Status :: 4 - Beta",
|
|
33
|
+
"Intended Audience :: Science/Research",
|
|
34
|
+
"Topic :: Scientific/Engineering :: Bio-Informatics",
|
|
35
|
+
"Topic :: Scientific/Engineering :: Chemistry",
|
|
36
|
+
"License :: OSI Approved :: MIT License",
|
|
37
|
+
"Programming Language :: Python :: 3",
|
|
38
|
+
"Programming Language :: Python :: 3.9",
|
|
39
|
+
"Programming Language :: Python :: 3.10",
|
|
40
|
+
"Operating System :: OS Independent",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
# Minimum Python version
|
|
44
|
+
requires-python = ">=3.9,<3.11"
|
|
45
|
+
|
|
46
|
+
# ---------------------------------------------------------------------------
|
|
47
|
+
# Core runtime dependencies
|
|
48
|
+
# ---------------------------------------------------------------------------
|
|
49
|
+
# Commercial solvers (Gurobi, CPLEX) are NOT listed here because they require
|
|
50
|
+
# separate license agreements and installation steps. See [project.optional-dependencies]
|
|
51
|
+
# for the optional gurobipy extra.
|
|
52
|
+
# pytfa is available at: https://github.com/EPFL-LCSB/pytfa
|
|
53
|
+
# ---------------------------------------------------------------------------
|
|
54
|
+
dependencies = [
|
|
55
|
+
# Metabolic modelling
|
|
56
|
+
"cobra==0.24.0",
|
|
57
|
+
"python-libsbml>=5.19.0",
|
|
58
|
+
"optlang==1.5.2",
|
|
59
|
+
|
|
60
|
+
# Thermodynamic flux analysis (ETFL dependency)
|
|
61
|
+
"pytfa>=0.9.1",
|
|
62
|
+
|
|
63
|
+
# Symbolic mathematics (ETFL uses sympy internals; v1.6.x required for
|
|
64
|
+
# compatibility with pytfa and the bundled ETFL code)
|
|
65
|
+
"sympy==1.6.2",
|
|
66
|
+
|
|
67
|
+
# Numerical / data
|
|
68
|
+
"numpy>=1.23,<2.0",
|
|
69
|
+
"scipy>=1.13",
|
|
70
|
+
"pandas>=1.3.5,<2.0",
|
|
71
|
+
|
|
72
|
+
# Visualisation
|
|
73
|
+
"matplotlib>=3.9",
|
|
74
|
+
|
|
75
|
+
# Graph utilities (used by cobra internals)
|
|
76
|
+
"networkx>=3.2",
|
|
77
|
+
|
|
78
|
+
# Bioinformatics
|
|
79
|
+
"biopython>=1.85",
|
|
80
|
+
|
|
81
|
+
# Excel I/O for results export
|
|
82
|
+
"openpyxl>=3.1",
|
|
83
|
+
"xlrd>=2.0",
|
|
84
|
+
|
|
85
|
+
# Data validation (pydantic v1 API; v2 is not compatible)
|
|
86
|
+
"pydantic>=1.10,<2.0",
|
|
87
|
+
|
|
88
|
+
# Progress bars
|
|
89
|
+
"tqdm>=4.60",
|
|
90
|
+
|
|
91
|
+
# Terminal output
|
|
92
|
+
"rich>=13.0",
|
|
93
|
+
|
|
94
|
+
# Miscellaneous
|
|
95
|
+
"six>=1.16",
|
|
96
|
+
"python-dateutil>=2.9",
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
# ---------------------------------------------------------------------------
|
|
100
|
+
# Optional dependencies (extras)
|
|
101
|
+
# ---------------------------------------------------------------------------
|
|
102
|
+
[project.optional-dependencies]
|
|
103
|
+
|
|
104
|
+
# Commercial solvers — install only if you hold a valid license
|
|
105
|
+
gurobi = [
|
|
106
|
+
"gurobipy>=10.0",
|
|
107
|
+
]
|
|
108
|
+
cplex = [
|
|
109
|
+
# IBM CPLEX Python API must be installed manually from the CPLEX directory;
|
|
110
|
+
# the PyPI package below is the community/stub package. For the full solver
|
|
111
|
+
# install CPLEX and run: python <cplex>/python/setup.py install
|
|
112
|
+
"cplex>=22.1",
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
# Transcriptomics integration (GIMME example requires troppo)
|
|
116
|
+
omics = [
|
|
117
|
+
"troppo>=0.1",
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
# Development and testing
|
|
121
|
+
dev = [
|
|
122
|
+
"pytest>=8.0",
|
|
123
|
+
"build>=1.0",
|
|
124
|
+
"twine>=5.0",
|
|
125
|
+
"ruff>=0.4",
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
# Install everything (except commercial solvers which need manual setup)
|
|
129
|
+
all = [
|
|
130
|
+
"strainOptimizer[omics,dev]",
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
# ---------------------------------------------------------------------------
|
|
134
|
+
# Project URLs (shown on the PyPI page)
|
|
135
|
+
# ---------------------------------------------------------------------------
|
|
136
|
+
[project.urls]
|
|
137
|
+
Homepage = "https://github.com/hongzhonglu/strainOptimizer"
|
|
138
|
+
Repository = "https://github.com/hongzhonglu/strainOptimizer"
|
|
139
|
+
"Bug Tracker" = "https://github.com/hongzhonglu/strainOptimizer/issues"
|
|
140
|
+
Documentation = "https://github.com/hongzhonglu/strainOptimizer/blob/main/README.md"
|
|
141
|
+
"Zenodo Archive" = "https://doi.org/10.5281/zenodo.20770724"
|
|
142
|
+
|
|
143
|
+
# ---------------------------------------------------------------------------
|
|
144
|
+
# Package discovery
|
|
145
|
+
# ---------------------------------------------------------------------------
|
|
146
|
+
[tool.setuptools.packages.find]
|
|
147
|
+
where = ["src"]
|
|
148
|
+
|
|
149
|
+
# Include model files and data bundled inside the package
|
|
150
|
+
[tool.setuptools.package-data]
|
|
151
|
+
"*" = ["*.json", "*.xml", "*.csv", "*.tsv", "*.xlsx", "*.yaml", "*.yml"]
|
|
152
|
+
|
|
153
|
+
# ---------------------------------------------------------------------------
|
|
154
|
+
# Build / upload workflow (for reference — not executed by setuptools)
|
|
155
|
+
# ---------------------------------------------------------------------------
|
|
156
|
+
# To build and upload to PyPI:
|
|
157
|
+
#
|
|
158
|
+
# pip install build twine
|
|
159
|
+
# python -m build # creates dist/*.whl and dist/*.tar.gz
|
|
160
|
+
# twine check dist/* # validate metadata before upload
|
|
161
|
+
# twine upload dist/* # upload to PyPI (prompts for credentials)
|
|
162
|
+
#
|
|
163
|
+
# For a test upload first:
|
|
164
|
+
# twine upload --repository testpypi dist/*
|
|
165
|
+
#
|
|
166
|
+
# Then verify installation from TestPyPI:
|
|
167
|
+
# pip install --index-url https://test.pypi.org/simple/ strainOptimizer
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from strainOptimizer.simulation import mopa,moma
|
|
2
|
+
|
|
3
|
+
def calculate_FCC_by_abundance(protID,model,productID,c_source='r_1714_REV', c_uptake=10, growthID='r_2111',objective='r_4046',objective_direction='max',delta_conc=1):
|
|
4
|
+
"""
|
|
5
|
+
Calculate the flux control coefficient (FCC) for a given product and growth reaction by disturb enzyme abundance.
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
model (cobra.Model): The GEM model object.
|
|
9
|
+
c_source (str): The reaction ID of the carbon source uptake reaction. default is 'r_1714_REV' (glucose uptake).
|
|
10
|
+
c_uptake (float): The uptake rate of the carbon source.
|
|
11
|
+
productID (str): The reaction ID of the product output reaction.
|
|
12
|
+
growthID (str): The reaction ID of the growth reaction.
|
|
13
|
+
protID (str): The protein ID to calculate FCC for.
|
|
14
|
+
objective (str): The reaction ID of the objective reaction. default is NGAM (r_4046).
|
|
15
|
+
objective_direction (str): The direction of the objective reaction. 'max' or 'min'. default is 'max'.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
tuple: FCCg, FCCp
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
# calculate the reference strain by maximizing NGAM
|
|
22
|
+
# ref_growth=0.2
|
|
23
|
+
with model:
|
|
24
|
+
model.reactions.get_by_id(c_source).bounds = (c_uptake, c_uptake) # set uptake rate
|
|
25
|
+
model.objective = growthID
|
|
26
|
+
model.objective_direction='max'
|
|
27
|
+
ref_growth=model.slim_optimize()/4 # set growth rate to 25% of max to allow for production
|
|
28
|
+
model.objective=productID
|
|
29
|
+
model.objective_direction='max'
|
|
30
|
+
max_production=model.slim_optimize()
|
|
31
|
+
ref_production=max_production/4
|
|
32
|
+
model.reactions.get_by_id(productID).bounds = (ref_production, 1000)
|
|
33
|
+
model.reactions.get_by_id(growthID).bounds = (ref_growth, 1000) # set growth reaction bounds
|
|
34
|
+
|
|
35
|
+
model.objective = objective # NGAM maximize as objective
|
|
36
|
+
model.objective_direction=objective_direction
|
|
37
|
+
ref_solution= model.optimize()
|
|
38
|
+
|
|
39
|
+
# calculate FCCg and FCCp
|
|
40
|
+
with model:
|
|
41
|
+
# overexpression for target protein
|
|
42
|
+
ref_conc=ref_solution.fluxes[protID]
|
|
43
|
+
new_conc=ref_conc*(1+delta_conc) # increase protein concentration by delta_conc
|
|
44
|
+
# set the protein concentration
|
|
45
|
+
model.reactions.get_by_id(protID).lower_bound= new_conc
|
|
46
|
+
|
|
47
|
+
solution=mopa(model,reference_solution=ref_solution,linear=True)
|
|
48
|
+
# solution=moma(model,reference_solution=ref_solution,linear=False)
|
|
49
|
+
|
|
50
|
+
new_growth=solution.fluxes[growthID]
|
|
51
|
+
new_production=solution.fluxes[productID]
|
|
52
|
+
|
|
53
|
+
# FCCg
|
|
54
|
+
FCCg= ((new_growth-ref_growth)/ref_growth)/delta_conc
|
|
55
|
+
# calculate FCCp
|
|
56
|
+
FCCp=((new_production-ref_production)/ref_production)/delta_conc
|
|
57
|
+
# print('growth:',new_growth,'vs',ref_growth,'production:',new_production,'vs',ref_production)
|
|
58
|
+
|
|
59
|
+
return FCCg, FCCp
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def calculate_FCC_by_kcat(protID,model,productID, c_uptake=10, growthID='r_2111',delta_kcat=1):
|
|
63
|
+
'''
|
|
64
|
+
Calculate the flux control coefficient (FCC) for a given product and growth reaction by disturb enzyme kcat.
|
|
65
|
+
v/kcat<=protein_pool/MW
|
|
66
|
+
v/(kcat*(1+delta_kcat))<=protein_pool/MW
|
|
67
|
+
therefore, disturb kcat could be processed by modify the draw protein reaction coefficient
|
|
68
|
+
v/kcat<=protein_pool*(1+delta_kcat)/MW
|
|
69
|
+
v/kcat<=protein_pool/(MW/(1+delta_kcat))
|
|
70
|
+
MW'=MW/(1+delta_kcat)
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
model (cobra.Model): The GEM model object.
|
|
74
|
+
c_uptake (float): The uptake rate of the carbon source.
|
|
75
|
+
productID (str): The reaction ID of the product output reaction.
|
|
76
|
+
growthID (str): The reaction ID of the growth reaction.
|
|
77
|
+
protID (str): The protein ID to calculate FCC for.
|
|
78
|
+
'''
|
|
79
|
+
c_source='r_1714_REV' # glucose uptake reaction
|
|
80
|
+
model.reactions.get_by_id(c_source).bounds = 0, c_uptake # set uptake rate
|
|
81
|
+
with model:
|
|
82
|
+
model.objective=productID
|
|
83
|
+
model.objective_direction='max'
|
|
84
|
+
ref_production=model.slim_optimize()
|
|
85
|
+
|
|
86
|
+
model.objective = growthID
|
|
87
|
+
model.objective_direction='max'
|
|
88
|
+
ref_growth=model.slim_optimize()
|
|
89
|
+
|
|
90
|
+
# desturbe kcat
|
|
91
|
+
with model:
|
|
92
|
+
prot_pool=model.metabolites.get_by_id('prot_pool[c]')
|
|
93
|
+
ref_mw=model.reactions.get_by_id(protID).metabolites[prot_pool]
|
|
94
|
+
model.reactions.get_by_id(protID).metabolites[prot_pool]=ref_mw/(1+delta_kcat)
|
|
95
|
+
|
|
96
|
+
model.objective = productID
|
|
97
|
+
model.objective_direction='max'
|
|
98
|
+
new_production=model.slim_optimize()
|
|
99
|
+
|
|
100
|
+
model.objective = growthID
|
|
101
|
+
model.objective_direction='max'
|
|
102
|
+
new_growth=model.slim_optimize()
|
|
103
|
+
|
|
104
|
+
FCCg=((new_growth-ref_growth)/ref_growth)/delta_kcat
|
|
105
|
+
FCCp=((new_production-ref_production)/ref_production)/delta_kcat
|
|
106
|
+
|
|
107
|
+
return FCCg,FCCp
|
|
108
|
+
|
|
109
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
'''Load standard datasets foe strain design algorithm evaluation
|
|
3
|
+
'''
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
import os
|
|
7
|
+
# get the path of this file
|
|
8
|
+
FILE_PATH = os.path.dirname(os.path.abspath(__file__))
|
|
9
|
+
def load_experiment_targets(product:str, data_dir=FILE_PATH+'/../../../data/experiment_targets'):
|
|
10
|
+
'''Load experiment targets for a specific product
|
|
11
|
+
'''
|
|
12
|
+
available_products = [f.replace('_exp_targets.tsv','') for f in os.listdir(data_dir) if f.endswith('_exp_targets.tsv')]
|
|
13
|
+
if product not in available_products:
|
|
14
|
+
print('Available products:', available_products)
|
|
15
|
+
raise ValueError('The product %s is not available!' % product)
|
|
16
|
+
else:
|
|
17
|
+
df = pd.read_csv(os.path.join(data_dir, product+'_exp_targets.tsv'), sep='\t', index_col=0)
|
|
18
|
+
return df
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def calculate_exp_consistency(predict_result, exp_data, show=True, merge_ko_kd=False):
|
|
22
|
+
'''
|
|
23
|
+
Calculate the experimental consistency of the prediction results by comparing the predicted gene targets with the experimental gene targets.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
merge_ko_kd: if True, treat KO and KD as one down-regulation category ('KD') before comparison.
|
|
27
|
+
'''
|
|
28
|
+
predict_result = predict_result[predict_result['action'].isin(['OE', 'KD', 'KO'])].copy()
|
|
29
|
+
exp_data = exp_data.copy()
|
|
30
|
+
|
|
31
|
+
if merge_ko_kd:
|
|
32
|
+
predict_result['action'] = predict_result['action'].replace('KO', 'KD')
|
|
33
|
+
exp_data['action'] = exp_data['action'].replace('KO', 'KD')
|
|
34
|
+
|
|
35
|
+
predict_group = predict_result.groupby('action')
|
|
36
|
+
exp_group = exp_data.groupby('action')
|
|
37
|
+
exp_consistency = dict()
|
|
38
|
+
overall_exp_num = 0
|
|
39
|
+
overall_hit_num = 0
|
|
40
|
+
overall_predict_num = 0
|
|
41
|
+
for key in exp_group.groups.keys():
|
|
42
|
+
exp_geneList = exp_group.get_group(key).index.tolist()
|
|
43
|
+
try:
|
|
44
|
+
predict_geneList = predict_group.get_group(key).index.tolist()
|
|
45
|
+
except:
|
|
46
|
+
predict_geneList = []
|
|
47
|
+
hit_geneList = list(set(exp_geneList).intersection(set(predict_geneList)))
|
|
48
|
+
overall_exp_num += len(exp_geneList)
|
|
49
|
+
overall_hit_num += len(hit_geneList)
|
|
50
|
+
overall_predict_num += len(predict_geneList)
|
|
51
|
+
exp_consistency[key] = {'exp': exp_geneList, 'predict': predict_geneList, 'hit': hit_geneList,
|
|
52
|
+
'exp_num': len(exp_geneList), 'hit_num': len(hit_geneList),
|
|
53
|
+
'consistency': len(set(exp_geneList).intersection(set(hit_geneList))) / len(
|
|
54
|
+
exp_geneList)}
|
|
55
|
+
if overall_predict_num==0:
|
|
56
|
+
return None
|
|
57
|
+
exp_consistency['overall'] = {'exp_num': overall_exp_num, 'hit_num': overall_hit_num,
|
|
58
|
+
'predict_num': overall_predict_num,
|
|
59
|
+
'consistency': overall_hit_num / overall_exp_num,
|
|
60
|
+
'precision': overall_hit_num / overall_predict_num}
|
|
61
|
+
|
|
62
|
+
if show==True:
|
|
63
|
+
for key in exp_consistency.keys():
|
|
64
|
+
print(f'{key}:')
|
|
65
|
+
print(exp_consistency[key])
|
|
66
|
+
|
|
67
|
+
return exp_consistency
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def gene_id_to_name(geneIDlist,annotation_file=FILE_PATH+'/../../../data/s288c_geneNames.csv'):
|
|
71
|
+
df=pd.read_csv(annotation_file,index_col=0)
|
|
72
|
+
df_geneName=df[df.index.isin(geneIDlist)]['geneName']
|
|
73
|
+
return df_geneName
|